home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 July / Macworld (1999-07).dmg / Shareware World / Info / For Developers / Mops 3.4.sea / Mops ƒ / zClass < prev    next >
Text File  |  1999-01-23  |  69KB  |  2,873 lines

  1. (*    file zClass
  2.  
  3. This file is part of the PPC version of the high-level class/object
  4. implementation.  It's a "z" file - it's not target compiled, but is
  5. loaded on the PPC itself.  Some of the PPC class-related code is 
  6. target compiled in qpClass, since we need it while we're still target 
  7. compiling.  Originaly I wanted to get ALL the class implementation
  8. into qpClass, but this proved to bristle with intractible problems, 
  9. so here we include everything that didn't  make it, which is quite a
  10. lot!
  11.  
  12. *)
  13.  
  14. \ Note: for all the class/object formats, see cg1.
  15.  
  16.  
  17. 34    constant    IFA_offset
  18.  
  19. : ]C    true  -> cstate ;        immediate
  20. : C[    false -> cstate ;        immediate
  21.  
  22. \ these are defined in qpClass:
  23.  
  24. \    0    value    PUB/PRIV    \ -1 private, 1 public, 0 default - for ivars and methods
  25. \ false    value    STATIC?        \ true if following ivars are to be static
  26. \    0    value    ^COMP_CLASS    \ addr of the class we're currently compiling
  27. \    0    value    PIVAR        \ hashed name of any public ivar we're accessing
  28. \    0    value    PIVSEL        \ hashed selector of any msg being sent to
  29.                             \  to a public ivar
  30.  
  31. \    0    value    NEWOBJECT    \ addr of object being created
  32. \    0    value    #SUP        \ number of superclasses for current class
  33. \    0    value    SUPERS_TO_SKIP
  34. \    0    value    INITID
  35.  
  36.  
  37.     0    value    thisM
  38.     0    value    superM
  39.     0    value    tempObjs    \ gets addr of class Dummy which we use for temp objects
  40.  
  41. false    value    bind_to_reg?
  42. false    value    register_request?
  43.  
  44.     0    value    reg_for_bind
  45.     0    value    regcode_for_bind
  46.     
  47.     0    value    #PL4temps
  48.     0    value    #FPL4temps
  49.     0    value    #VL4temps
  50.  
  51.  
  52. \                ===============================
  53. \                        UTILITY WORDS
  54. \                ===============================
  55.  
  56. : PRIVATE        -1 -> pub/priv  ;        \ following methods and ivars will be private
  57. : PUBLIC         1 -> pub/priv  ;        \ following methods and ivars will be public
  58.  
  59. : END_PRIVATE    0 -> pub/priv  ;        \ back to the default
  60. : END_PUBLIC    0 -> pub/priv  ;        \ ditto
  61.  
  62.  
  63. \ TOfind looks for a temp (local) object.
  64.  
  65. : TOfind  { str-addr -- ^ivar offs T | -- str-addr F  }
  66.     str-addr
  67.     tempObjs? NIF  false  EXIT  THEN    \ out if no temp objects
  68.     hash
  69.     tempObjs <findIV>
  70.     IF                    \ ( -- ^ivar offs xdispl-offs )
  71.         drop        \ xdispl-offs must be zero for class Dummy
  72.         dup $ FFFE >=
  73.         IF            \ self or super - mustn't match these in class Dummy!
  74.             2drop  str-addr false  EXIT
  75.         THEN
  76.         true
  77.     ELSE
  78.         str-addr false
  79.     THEN
  80. ;
  81.  
  82.  
  83. (*
  84. LocFind will be called from Ufind, which is the vector that gets first
  85. shot at recognizing a word.  It looks at all the possibilities
  86. involving local names, which are not in the regular dictionary.  These
  87. possibilities are: named parms/locals, local objects, and if a class
  88. is being compiled, ivars of this class.
  89.  
  90. In the latter case, we arrange for the ivar's address to be pushed at
  91. run time simply by compiling ^base followed by an add of the ivar's
  92. offset - our code generation will produce optimal code for this.  We
  93. then have to return the xt of some word to keep FIND happy - we don't
  94. need to compile anything else, so we use the xt of NULL and return a 1
  95. instead of True - this makes FIND think it's immediate.  So NULL is
  96. executed immediately, which does precisely nothing.
  97.  
  98. The one exception to this is if the "ivar" turns out to be SELF or SUPER
  99. - in this case we need to call the nucleus word SELF which works out
  100. the right base address (this is what happened pre-2.5).  Here we keep
  101. FIND happy by pushing the xt of SELF and True, so that it sees we've
  102. found SELF.
  103. *)
  104.  
  105.  
  106. : LocFind  { str-addr \ flags reg# -- cfa T  |  -- str-addr F }
  107.     str-addr Pfind    ?dup  ?EXIT        \ Found a named parm/local
  108.     TOfind
  109.     IF                                \ Found temp obj
  110.         swap iffa w@  -> flags
  111.         flags 4 >> $ F and  ?dup
  112.         IF                \ it's in a register
  113.             ( offs regcode )  nip
  114.             ( regcode )  flags 8 >> $ 1F and  ( reg# )  reg_name
  115.         ELSE
  116.             postpone locReg  postpone literal  postpone +
  117.         THEN
  118.         ['] null  1  EXIT
  119.     THEN
  120.  
  121. \ Now we look for an ivar name
  122.  
  123.     cstate  NIF  false  EXIT  THEN        \ search fails if we're not compiling
  124.                                         \  a class
  125.     dup hash ^comp_class IFA_offset false  (findM)
  126.     IF                                    \ Found ivar
  127.         nip nip                            \ don't need embedded obj offs or
  128.                                         \  string addr
  129.         12 + w@                            \ ivar offset
  130.         dup $ FFFE >=                    \ is it SELF or SUPER (just used in
  131.                                         \  isolation)?
  132.         IF    drop  
  133.             " (^base) 4- dup w@x + 8 +" evaluate        \ i.e. SELF - but I can't evaluate
  134.                                                         \  that, or we'll end up here again
  135.                                                         \  and infinitely recurse!
  136.         ELSE
  137.             postpone (^base) postpone literal  postpone +
  138.         THEN
  139.         ['] null  1
  140.     ELSE    false
  141.     THEN  ;
  142.  
  143.  
  144. \ 0 -> quitvec   0 -> abortvec   0 -> objInit        \ clear vectors
  145. \ ' pfind  -> ufind
  146.  
  147. \ in qpClass
  148. \ : ?CLASS        \ Error if not compiling a class definition.
  149. \     cstate 0=  ?error 115  ;
  150.  
  151.  
  152. \                        ========================
  153. \                                BINDING
  154. \                        ========================
  155.  
  156.     0    value    OBJ_BASE
  157.     0    value    OBJ_DISPL
  158.     0    value    OBJ_LOCAL_DISPL
  159.     0    value    OBJ_IND
  160.  
  161. false    value    SELF?
  162.  
  163.  
  164. (*    Note: obj_ind, which we use in 68k Mops, isn't needed on the PPC.
  165.     we don't now use an indirect count in an OD, but just do repeated fetches
  166.     to different registers till we come to the data we want.
  167.     On the 68k, as far as I can tell, the only time obj_ind wasn't zero was
  168.     when we did an early bind to an addr on the stack, or to an objPtr (which
  169.     used the same code).  This was also the reason we kept two offsets
  170.     - obj_displ and obj_local_displ.  Obj_displ applied before any indirection
  171.     steps, and obj_local_displ after.  On the PPC we were able to get rid of
  172.     these complexities.
  173. *)
  174.  
  175. : (OBJ)        \ Called from within an inline method.  Passes the object's
  176.             \  base and displacement to Handlers to generate the correct
  177.             \  address.  Optimization will then apply.
  178.     bind_to_reg?
  179.     IF
  180.         regcode_for_bind  reg_for_bind  reg_name  EXIT
  181.     ELSE
  182.         obj_base obj_displ
  183.         obj_ind  genaddr
  184.         obj_local_displ  postpone literal  postpone +
  185.     THEN
  186. ;
  187.  
  188.  
  189. : (IX)
  190.  
  191.     (*    Called from within an inline method.  Compiles code to generate
  192.         the indexed address.
  193.         ^comp_class has been set by inl_bind to the class of the obj
  194.         we're binding to.  One tricky point is that to access the indexed
  195.         area, we have to use the dlen value in this class, not the class
  196.         of the method we're calling (which may be a superclass).  But
  197.         the obj_local_displ has already had the embedded object offset
  198.         added in (if any).  We have to ignore this, since we're using 
  199.         the object's class, not the method's.  When the method was found,
  200.         the value emb_obj_offs was set to this offset, so we subtract
  201.         it here.
  202.     *)
  203.  
  204.     ^comp_class dlen&xwid  swap
  205.     self?
  206.     IF  drop  -1  ELSE  #off-align  6 +  THEN
  207.     obj_base obj_displ obj_local_displ
  208.     emb_obj_offs -
  209.     obj_ind  ^comp_class ffa w@
  210.     genxaddr  ;
  211.  
  212.  
  213. : ^BASE
  214.     compinline?
  215.     IF        (obj)
  216.     ELSE    postpone (^base)
  217.     THEN  ;            immediate
  218.  
  219.  
  220. : ^ELEM
  221.     compinline?
  222.     IF        (ix)
  223.     ELSE    " (^elem)"  evaluate            \ need PPC version
  224.     THEN  ;            immediate
  225.  
  226.  
  227. : OBJ    postpone ^base  ;    immediate        \ for backward compatibility
  228. : IX    postpone ^elem  ;    immediate        \ ditto
  229.  
  230.  
  231. forward enter_meth_in_mod
  232.  
  233. local  EARLY_BIND  { oCfa oBase oDispl oLDispl oind slf? \ ^mod ptr -- }
  234.  
  235.  
  236. : INL_BIND    \ ( -- b )
  237.     ^comp_class  cstate  self?                    \ Save over upcoming evaluate
  238.     slf? NIF  objClass -> ^comp_class  THEN        \ Set ^comp_class and cstate
  239.     true -> cstate                                \  so ivars are accessible
  240.     slf? -> self?
  241.     oCfa  inline_h                                \ calls evaluate
  242.     -> self?  -> cstate  -> ^comp_class            \ Restore
  243. ;
  244.  
  245.  
  246. : MODULE_BIND
  247.     heldMod  dup
  248.     @ @            \ get mod handle and dereference - addr of mod start
  249.     -> ^mod
  250.     ^mod 8 + -> ptr            \ self-rel addr of exports table
  251.     ptr @ ++> ptr            \ ptr -> start of table
  252.     0 -> methIndex
  253.     BEGIN
  254.         ptr @ dup 0<
  255.         IF            \ we have a problem - we didn't find the entry in the
  256.                     \  module's export table, though it ought to be there!
  257.                     \ Maybe heldMod should have been zero, and we shouldn't
  258.                     \  have been trying to do a module bind at all??
  259.             cr cr ." heldMod " heldMod .h  cr cr
  260.             heldMod 32 - 64 dump
  261.             198 die        \ "internal error"
  262.         THEN
  263.         ^mod +  oCfa =
  264.     NWHILE
  265.         4 ++> methIndex  4 ++> ptr
  266.     REPEAT
  267.     
  268. \ methIndex now has the export table offset for the method.
  269.     (obj)                        \ compile push of obj addr (clears heldMod!)
  270.  ( heldMod )  lit_addr            \ and a push of the module's addr
  271.     methIndex  postpone literal    \ and a push of export table offset
  272.     ['] enter_meth_in_mod  call_h
  273. ;
  274.  
  275.  
  276. : NORM_BIND
  277.     heldMod
  278.     IF      module_bind
  279.     ELSE    oCfa  (obj)  call_h        \ call_h will see by the handler code
  280.     THEN                            \  that this is a method, and do the
  281. ;                                    \  right things, hopefully
  282.  
  283. :loc  EARLY_BIND        \ { oCfa oBase oDispl oLDispl oind slf? -- }
  284.     obj_base  obj_displ  obj_local_displ  obj_ind        \ Save
  285.     oBase    -> obj_base            oDispl    -> obj_displ
  286.     OLdispl    -> obj_local_displ    oind    -> obj_ind
  287.     oCfa 2- w@  $ BD40 =
  288.     IF
  289.         inl_bind
  290.     ELSE
  291.         bind_to_reg?
  292.         IF    false -> bind_to_reg?
  293.             158 die        \ "You can only use inline methods with a register object"
  294.         THEN
  295.         norm_bind
  296.     THEN
  297.  
  298.     -> obj_ind  -> obj_local_displ
  299.     -> obj_displ  -> obj_base            \ Restore
  300. ;loc
  301.  
  302.  
  303. : BIND_TO_OBJ  { cfa ^obj offs -- }
  304.     cfa
  305.     -1                    \ -1 as "base" signals handlers to generate
  306.     ^obj                \  a normal dic addr.  We still carry the
  307.                         \  offs here since if we need to access the
  308.                         \  indexed area, we want the original obj addr,
  309.                         \  not some embedded object.
  310.     offs  0  false  early_bind  ;
  311.  
  312. : BIND_TO_STK  { xt \ svHeldMod -- }
  313.     heldMod -> svHeldMod  0 -> heldMod
  314.     xt hStkObj            \ ( -- xt base displ )
  315.     svHeldMod -> heldMod
  316.     0  0  false  early_bind  ;
  317.  
  318. : BIND_TO_IVAR  { cfa offs -- }
  319.     cfa  obj_base  obj_displ
  320.     obj_local_displ offs +
  321.     obj_ind  false  early_bind  ;
  322.  
  323. : BIND_TO_TMPOBJ  { cfa offs -- }
  324.     cfa
  325.     <'> locReg 3+ c@        \ current locReg number
  326.     offs
  327.     0 0 false  early_bind  ;
  328.  
  329. : BIND_TO_REG  { cfa -- }
  330.     true -> bind_to_reg?
  331.     cfa  0 0 0 0 false  early_bind
  332.     false -> bind_to_reg?
  333. ;
  334.  
  335.  
  336. : BIND_TO_SELF  { cfa offs -- }
  337.     cfa  obj_base  obj_displ  offs  obj_ind  true  early_bind  ;
  338.  
  339.  
  340. \                    ============================
  341. \                            :CLASS  etc.
  342. \                    ============================
  343.  
  344. (*
  345. Here we set up some quantities so that we can send messages to SELF
  346. or SUPER.  These are treated syntactically as ivars, so to implement
  347. them we actually set up dummy ivars SELF and SUPER.
  348.  
  349. When we're processing a :CLASS definition, we plug the appropriate
  350. addresses into these ivars.  ^SELF is a word defined to return the
  351. addr of the dummy ivar SELF, so we can do the plugging.
  352. In the case of SUPER, there may be several superclasses, so we have
  353. to go through a class descriptor, since that's the only place we look
  354. for an n-way (a set of addresses).  So we set the "class" of SUPER
  355. to a dummy class SUPCL, which has no ivars or methods (so the search
  356. will pass right on by), and plug the superclass pointer of SUPCL to
  357. point to the current n-way for the superclasses of the class we're
  358. defining.
  359. *)
  360.  
  361.  
  362. \ : ^SELF        self_vbl  displace  ;
  363.  
  364.  
  365.  
  366. : :CLASS
  367.     ?exec  header  $ BC1D codeW,
  368.     CDP -> ^comp_class
  369.     0 -> pub/priv  0 -> #1st  0 -> #last
  370.     false -> rec?  false -> union?  false -> static?
  371.     307
  372. ;        immediate
  373.  
  374.  
  375. : MERGE_INFO  { ^sup ivlen \ ^wid wid prevWid -- dlen }
  376.     ^sup dlen&xwid  -> wid        \ indexed width of this superclass
  377.     ^sup ffa 1+ c@ 5 and        \ Merge "large" and "general" flags with
  378.     ^comp_class ffa 1+  cset    \  what we have already
  379.     wid  0EXIT                    \ If this superclass not indexed, we're done
  380.     
  381. \ This class is indexed - we need to check if prev classes were indexed
  382. \  and make sure the widths are compatible.
  383.  
  384.     ^comp_class dfa 2+  -> ^wid        \ Addr of wid field in class we're building
  385.     ^wid w@  -> prevWid            \ Get previous width
  386.     wid 32760 u>                \ "indexed width" of 32766/7 really means
  387.     IF                            \  obj_array.
  388.         prevWid                    \ In this case if we already have a width,
  389.         IF        prevWid -> wid    \  we use that,
  390.         ELSE    wid
  391.                 ivlen  -> wid    \ otherwise current ivar len becomes the width.
  392.  
  393.             ( old wid ) 32766 =
  394.                 IF        \ large_obj_array - mark boundary between ivars
  395.                         \  we are/aren't mapping to the indexed area
  396.                     ivlen aligned  ^comp_class xoffa w!
  397.                     wid aligned 4+  -> wid    \ and allow for ^class offset
  398.                                             \  and indexed area offset
  399.                                             \  before each element
  400.                 THEN
  401.         THEN
  402.     THEN
  403.     prevWid
  404.     NIF     wid  ^wid w!        \ If no prev width, set width & we're done
  405.     ELSE    prevWid wid <>  ?error 88        \ "Incompatible indexed widths"
  406.     THEN
  407. ;
  408.  
  409.  
  410. local    (SUP)   { \ ^supcl ivlen ^nway ^sup ^newClass thisLen -- }
  411.  
  412. : NEXT_SUPER    ( cfa -- )
  413.     chkClass  -> ^sup
  414.     ^sup relocCode,                    \ Add ^class to n-way
  415.     ^sup ivlen merge_info   -> thisLen
  416.     #sup IF                            \ If this is a subsequent class,
  417.         ivlen #align4  4+  -> ivlen    \  align and allow for ^class offset and
  418.                                     \  2 extra bytes padding
  419.     THEN
  420.     thisLen ++> ivlen                \ And add ivar length of new class
  421.     1 ++> #sup  ;
  422.  
  423.  
  424. : SUPERS_LOOP
  425.     BEGIN                        \ Loop over superclasses:
  426.         '                        \ cfa of next item on list
  427.         }or)? IF  drop  EXIT  THEN
  428.         ( cfa )  next_super            \ handle next superclass
  429. \        1super?  ?EXIT                \ Yerk has only one superclass
  430.     AGAIN  ;
  431.  
  432.  
  433. :loc  (SUP)
  434.     307 ?pairs                        \ Make sure we're in the right place
  435.     CDP -> ^newClass
  436.     46 ( classSize )  code_reserve            \ Space for class record
  437.     CDP -> ^nway                    \ n-way for superclasses will
  438.     0 -> ivlen  0 -> #sup            \  start here
  439.     ^newClass 2+ 32 bounds
  440.     DO  ^nway  i displ!  4 +LOOP    \ point methods links to nway
  441.     ^nway ^newClass IFA  displ!        \ and ivars link
  442.     false -> relocChk?
  443.     supers_loop                        \ Loop over superclasses
  444.     0 code,                            \ Terminate n-way
  445.     " SUPCL" sFind drop -> ^supcl
  446.     ^supcl 2+ 32 bounds
  447.     DO  ^nway  i displ!  4 +LOOP    \ we point the method and ivar links
  448.     ^nway                            \  in supcl to the n-way
  449.     ^supcl IFA  displ!
  450.  
  451.     ^comp_class xoffa w@
  452.     " SUPCL" sFind drop xoffa w!    \ and set xoffs in supCl
  453.  
  454.     ivlen ^comp_class dfa w!        \ Set total ivar length
  455. \    ^comp_class  ^self 8 +  reloc!    \ Store ^class in SELF
  456.     true -> relocChk?
  457.     postpone ]c                        \ In a class definition
  458.     308
  459. ;loc
  460.  
  461.  
  462. : SUPER{        ( false -> 1super? )   (sup)  ;        immediate
  463.  
  464. \ : SUPER(        postpone super{  ;                immediate
  465.  
  466. \ : <SUPER    true -> 1super?  (sup)    ;            immediate
  467.             \ For compatibility with Yerk -- only looks for 1 superclass
  468.  
  469.  
  470. : (;CL)
  471.     postpone [  postpone c[
  472. ;
  473.  
  474.  
  475. : ;CLASS
  476.     (;cl)  308 ?defn  ;            immediate
  477.  
  478.  
  479.    1    value    DFRSELID    \ 1 means no late bind going on - otherwise it's
  480.                                \  the selector we're late binding with
  481. true    value    SLCTRS?        \ Set false to treat selectors as normal words
  482.                             \  for full ANSI compatibility
  483.  
  484. : SEL?        \ ( addr -- addr b )  True if word at addr is a selector xxx:
  485.     slctrs?  NIF  false  EXIT  THEN
  486.     dup  count tuck  1- + c@  & :  =
  487.     swap 1 >  and  ;
  488.  
  489.  
  490. : GETSELECT            \ Gets a selector from the input stream
  491.     mword
  492.     sel?  not ?error 124
  493.     hash
  494.     1 -> dfrSelID  ;
  495.  
  496.  
  497. ' null    vect    GET1ST&LAST
  498. ' null    vect    DoCall1ST
  499. ' null    vect    DoCallLast
  500.  
  501.  
  502. : M_HEADER  { selID -- }    \ Builds a method header and entry sequence.
  503.                             \ Note: also called from the assembler.
  504.     selID ^comp_class MFA  selID  hashed-hdr    \ Build header
  505.     drop                            \ drop extra selID (needed by MFA)
  506.     CDP 4-  -> ^meth_link
  507.     pub/priv -1 =  1 and  codeW,    \ public/private flag (default is public)
  508.     0 codeW,                        \ padding for alignment
  509.     $ BE400000 code,                \ "handler code" for PPC methods,
  510.                                     \  and initial flag bytes
  511.     CDP 2- -> thisM                    \ Remember method cfa
  512. ;
  513.  
  514. \    0 codeW,                        \ space for parm flags (or do it in Mentry?)
  515. \    Mentry  ;                        \ Compile the entry sequence
  516.  
  517.  
  518. : :M { \ selID -- }            \ Starts compiling a method.
  519.  
  520.     CDP -> last_colon_defn            \ used by compile_call in checking where
  521.                                     \  a call is coming from
  522.     true -> method?
  523.     ?class
  524.     rec? ?error 191                    \ unmatched '{' in ivar list
  525.     0 -> superM
  526.     getSelect -> selID
  527.     10 -> cstate                    \ Means we've read :m, no call_1st yet
  528.  
  529.     selID ^comp_class MFA_offset true (findm)        \ is method already defined?
  530.     IF
  531.         -> superM
  532. \        warnings?
  533. \        IF    cr  CDP count type type# 182         \ "Method redefined"
  534. \        THEN
  535.         heldMod 
  536.         NIF  superM ^comp_class > ?error 183  THEN
  537.                                             \ - but if in same class, error
  538.         drop
  539.     THEN
  540.  
  541.     get1st&last  \ ?unHoldMod
  542.     CDP -> const_data_start
  543.     selID m_header                    \ Build method header
  544.     #1st #last +
  545.     IF  $ 80  thisM 5 - cset  THEN    \ set call1st/callLast flag
  546.     obj_base_reg -> obj_base        \ gpr20
  547.     0 -> obj_displ                    \ For any inline method calls
  548.     false ppc_entry                    \ Start to compile the method
  549.     drop 305                        \ change security marker to say method
  550.     doCall1st                        \ Compile any Call1st calls first
  551. ;        immediate
  552.  
  553. : ;M
  554.     true -> method?                \ things might have happened during the defn
  555.                                 \  to make it false, like compilation being
  556.                                 \  turned off and on.  This doesn't matter,
  557.                                 \  but we definitely need it true here.
  558.     #last IF  doCallLast  THEN
  559.     curr-def 2-  (;)
  560.     0 -> #1st  0 -> #last
  561.     305 ?defn  ;        immediate
  562.  
  563.  
  564. \    ============== Local sections for methods ==============
  565.  
  566. \ These function just like regular local sections.  The implementation
  567. \ is nearly the same.
  568.  
  569.     0    value    mloc_addr
  570.  
  571. : MLOCAL        \ Starts a local section for methods
  572.     local?  ?error 93  1 -> local?        \ We change it to the normal -1
  573.                                         \ as soon as "{" is read.
  574.     true -> localSect?
  575.     CDP -> CD_gpr_loc
  576.     postpone :m  drop
  577.     postpone [
  578.     CDP -> mloc_addr
  579.     $ 48000000  code,        \ uncond branch to be resolved by :mloc
  580.     private
  581. ;
  582.  
  583.  
  584. : :MLOC
  585.     public  ?loc  getSelect drop
  586.     CDP -> const_data_start
  587.     $ BE030000  code,            \ marks this as the :mloc position
  588.                                 \  (just for disassembly)
  589.     true -> method?
  590.     false -> local?                \ so entry sequence gets compiled
  591.     true -> mloc?                \ so const data gets handled properly
  592.     false ppc_entry                \ handle ppc proc entry
  593.     drop 309                    \ security marker for :mloc
  594.     curr-def
  595.       mloc_addr -> curr-def
  596.       PLentry
  597.     -> curr-def
  598.     tempObjs? IF  initTemps  THEN
  599. ;        immediate
  600.  
  601.  
  602. : ;MLOC
  603.     309 ?defn
  604.     false -> leaf?            \ let's just reduce the bug possibilities!
  605.     #last IF  doCallLast  THEN
  606.     mloc_addr 2-  (;)
  607. \    #last  IF  true -> method?  doCallLast  ( defnEnd)  false -> method?  THEN
  608.     0 -> #1st  0 -> #last
  609.     curr-def mloc_addr -    \ resolve the forward branch from MLOCAL
  610.     mloc_addr +!
  611.     false -> localSect?
  612. ;            immediate
  613.  
  614.  
  615. \    ================   INDEXED, GENERAL etc.   =================
  616.  
  617. \ These are words which can appear in a class declaration, in the
  618. \ position
  619.  
  620. \  :class someClass super{ someSuper }   general
  621.  
  622. \ They add attributes to the class.
  623.  
  624. : INDEXED        \ ( width -- )  Sets a class and its subclasses to indexed
  625.     ?class  ^comp_class dfa 2+  w!  ;
  626.  
  627. : LARGE  ;        \ in effect, this always applies on the PPC
  628.  
  629.  
  630. : into_flags  { new_flags -- }
  631.     ?class  ^comp_class ffa dup w@  new_flags or  swap w!  ;
  632.  
  633.  
  634. : GENERAL
  635.  
  636. (*    Sets the "general" option on a class, which will force an ivar of that class
  637.     to be a general object with a class pointer (so it can be late-bound to) even
  638.     if it's within a record.  Normally you should just not put such ivars in a
  639.     record, but using GENERAL gives a bit of extra security, for classes for which
  640.     you know that they will definitely be late-bound to.  (An attempt to late-bind
  641.     to an ivar without a class pointer will give the "not an object" error at run
  642.     time, which isn't easy to track down.)
  643.     Note that indexed classes are always general anyway.  Also if there's a message
  644.     sent to [self] somewhere in one of the methods, we know that the class *must*
  645.     be general, so in this case we simply set the general attribute.
  646. *)
  647.     4 into_flags  ;
  648.  
  649. (* moved to qpClass...
  650.  
  651. : CAN_BE_GPR        $ 30  into_flags  ;
  652. : CAN_BE_FPR        $ 40  into_flags  ;
  653. : CAN_BE_VR            $ 50  into_flags  ;
  654.  
  655. : ALIGNMENT  ( n -- )  8 << into_flags  ;        \ n is power of 2
  656.  
  657. *)
  658.  
  659. \                    ===========================
  660. \                            SELECTORS
  661. \                    ===========================
  662.  
  663. \ First, here are the special-purpose things which can follow a selector.
  664. \ These can't appear in isolation.
  665.  
  666. \ We allow ** and [] as synonyms of [ ] to late-bind to whatever is on the
  667. \ stack.  Note:  [] is used in JForth.
  668.  
  669. \ We also allow [self] as a synonym of [ self ]
  670.  
  671. : **        83 die  ;        \ "Has no meaning unless preceded by a selector"
  672. : []        83 die  ;
  673. : [SELF]    83 die  ;
  674. : SUPER>    83 die  ;
  675. : IVAR>        83 die  ;
  676. : CLASS_AS>    83 die    ;
  677.  
  678.  
  679. : ]
  680.     hide  dfrSelID  1 = IF   postpone ]  EXIT  THEN        \ if no late bind, this is a
  681.                                                         \  standard Forth ]
  682.     dfrSelID NIF  187 die  THEN        \ late bound public ivar reference
  683.                                     \  not implemented yet!
  684.     state
  685.     IF        251 ?pairs  dfrSelID  postpone literal
  686.             postpone send
  687.     ELSE    $ deadbeef $ 106 db        \ shouldn't happen
  688.             dfrSelID  send
  689.     THEN
  690.     1 -> dfrSelID  ;        immediate
  691.  
  692.  
  693. 100        constant    pubIvarTyp        \ &&& temp
  694. false    value        need_class?
  695.  
  696. false    value        implicit_late_bind?        \ true for pre-2.7 auto-late-bind
  697.                                             \  to locals or values
  698.  
  699. (* REFTOKEN ( -- cfa tokenType | -- various type )
  700.    is called when we've parsed a selector - it determines the type of the
  701.    following word.
  702.    
  703.    The order of checking determines the priority of names.  Up to 2.6 we
  704.    checked for locals first, but this was a bad idea since a local could
  705.    have the same name as an object, and implicit late binding to locals
  706.    was legal.  This wouldn't show up until a crash at run time.  So now we
  707.    check for temp objects, then ivars, then locals IF implcit_late_bind? is
  708.    true.
  709.  
  710.    "various" will be the cfa of whatever came after the selector, or
  711.    ( offset ^ivar ) for ivars and temp objects (which are treated as ivars
  712.    of the class Dummy).
  713. *)
  714.  
  715. : REFTOKEN        \ ( -- cfa tokenType | -- various type )
  716.  
  717.     false -> need_class?
  718.     Mword                                    \ grab next word
  719.     TOfind    IF  tmpObjTyp    EXIT  THEN        \ check for temp object
  720.     IVfind    IF  ivarTyp        EXIT  THEN        \ check for ivar
  721.     
  722.     implicit_late_bind?
  723.     IF    Pfind    IF  locTyp    EXIT  THEN        \ check for named parm/locals
  724.     THEN
  725.  
  726.     ( here )  dup thread dup @ +  (find)  0=  ?error 125
  727.     dup ['] **            =  IF  lbTyp                            EXIT  THEN
  728.     dup ['] []            =  IF  lbTyp                            EXIT  THEN
  729.     dup ['] [            =  IF  bktTyp                            EXIT  THEN
  730.     dup ['] [self]        =  IF  lbSelfTyp                        EXIT  THEN
  731.     dup ['] super>        =  IF  superTyp                            EXIT  THEN
  732.     dup ['] ivar>        =  IF  pubIvarTyp                        EXIT  THEN
  733.     dup ['] class_as>    =  IF  true -> need_class?  classTyp    EXIT  THEN
  734.     dup hdlr
  735.     CASE
  736.         $ BC0B        OF    >obj  objTyp    ENDOF
  737.         $ BC1D        OF    classTyp        ENDOF
  738.         $ BC1F        OF    objPtrTyp        ENDOF
  739.         $ BC03        OF    valTyp            ENDOF
  740.                                 \ Note: here we can treat vectors as words.
  741.  
  742.         126 die                    \ "Not an object name"
  743.     ENDCASE
  744.  
  745. \ but if we got wordTyp or valTyp, it's only legal if implicit_late_bind?
  746. \  is true
  747.     implicit_late_bind?  ?EXIT        \ all OK - done
  748.     dup wordTyp =  over valTyp =  or
  749.     IF  126 die  THEN
  750. ;
  751.  
  752.  
  753. \ These words handle the binding of a selector to whatever follows it.
  754.  
  755. (*    FIX_PIVAR does the housekeeping for accessing a public ivar.  When we
  756.     encounter  msg: ivar>  then we store the selector in pivSel, and the
  757.     hashed ivar name in pivar.  We then continue with a zero "selector",
  758.     which signals that it's a public ivar access, and leads to us being
  759.     called back here to fix everything up once we've got the class.
  760. *)
  761.  
  762. : FIX_PIVAR  { ^class in_class? \ ^ivar offs xdispl-offs -- cfa offs xdispl-offs }
  763.  
  764.     ^class ?>classInMod -> ^class
  765.  
  766.     pivar ^class <findIV>            \ ( ^ivar offs xdispl-offs true  OR  false )
  767.     0= ?error 192                    \ "ivar not found"
  768.     -> xdispl-offs  -> offs  -> ^ivar
  769.     ^ivar iffa w@                     \ get ivar flags
  770.     dup 4 and 0=    ?error 193        \ ivar not public
  771.     2 and                            \ static flag
  772.     in_class?
  773.     IF        0=  ?error 197            \ ivar not static
  774.     ELSE    ?error 195                \ wrong syntax for public static ivar
  775.     THEN
  776.  
  777. \ now we find the method in the ivar's class
  778.  
  779.     pivSel ^ivar  ivFindM drop        \ %%% don't worry about large_obj_arrays
  780.                                     \  which are ivars yet!
  781.   ( cfa  offs-within-ivar )
  782.     in_class?
  783.     IF            \ for public static ivars, the "offset" we return is
  784.                 \  actually the ivar's real data address.
  785.         drop ^ivar  static_ivar_offs +  @abs  -> offs
  786.     ELSE
  787.         ++> offs
  788.      THEN
  789.      offs  xdispl-offs
  790. ;
  791.  
  792.  
  793. \ PUBLIC_STATIC_IVAR_REF handles a message bind to a public static ivar
  794. \ (done via the  msg: ivar> in_class someClass  syntax)
  795.  
  796. : PUBLIC_STATIC_IVAR_REF
  797.     refToken
  798.     classTyp <>  ?error 196            \ class name must follow in_class
  799.     true  fix_pivar drop            \ %%% don't worry about large_obj_arrays
  800.                                     \  which are public static ivars yet!
  801.     0  bind_to_obj
  802. ;
  803.  
  804.  
  805. \ OBJREF handles a reference to a normal object.
  806.  
  807. : OBJREF  { selID ^obj \ cfa offs xdispl-offs -- }
  808.     selID
  809.     IF    selID ^obj  objFindm
  810.     ELSE                \ it's a public ivar reference in the referenced object
  811.         ^obj >class  false  fix_pivar
  812.     THEN
  813.  
  814.   ( cfa offs xdispl-offs )  -> xdispl-offs  -> offs  -> cfa
  815.  
  816.     xdispl-offs
  817.     IF    
  818.         ^obj xdispl-offs +  lit_addr
  819.         " dup @ +" evaluate
  820.         offs IF                \ will normally be zero
  821.                 offs postpone literal
  822.                 " +" evaluate
  823.             THEN
  824.         cfa bind_to_stk  EXIT
  825.     THEN
  826.  
  827.      cfa ^obj offs bind_to_obj
  828. ;
  829.  
  830.  
  831. \ IVARREF handles a reference to an ivar.
  832.  
  833. : IVARREF  { selID ^ivar offs xdispl-offs \ cfa stat? -- }
  834.  
  835.     heldMod  0 -> heldMod                \ save
  836.     offs  $ FFFE >=  -> selfRef?        \ if self or super.  Allows private
  837.                                         \ methods to be found by (findm)
  838.     selfRef?
  839.     IF  supers_to_skip -> sups2skip        \ sups2skip is interrogated by (findm).
  840.                                         \  This must only be done if self or
  841.                                         \  super is the target.
  842.         0 -> offs                        \ "real" offset is zero
  843.     ELSE
  844.         ^ivar iffa w@ 2 and  -> stat?    \ static ivar?
  845.     THEN
  846.     selID
  847.     IF    selID ^ivar ivFindM            \ %%% don't worry about large_obj_arrays
  848.                                     \  which are ivars yet!
  849.         selfRef? IF -> xdispl-offs  ELSE drop THEN
  850.  
  851.         ++> offs                    \ add embedded obj base offs to ivar offs
  852.         -> cfa
  853.         0 -> sups2skip  0 -> supers_to_skip
  854.  
  855.         selfRef?
  856.         IF    xdispl-offs
  857.             IF    xdispl-offs postpone literal
  858.                 " ^base + dup @ +"  evaluate
  859.                 cfa  bind_to_stk
  860.             ELSE
  861.                 cfa offs bind_to_self  false -> selfRef?
  862.             THEN
  863.     \        ?unholdMod
  864.             -> heldMod   EXIT
  865.         THEN
  866.  
  867.     ELSE                \ it's a public ivar reference within the referenced ivar
  868.         ^ivar ^iclass false  fix_pivar drop        \ %%% don't worry about large_obj_arrays
  869.                                                 \  which are ivars yet!
  870.         ++> offs  -> cfa
  871.     THEN
  872.  
  873.     stat?
  874.     IF    cfa  ^ivar static_ivar_offs + @abs  0  bind_to_obj
  875.     \    ?unholdMod  
  876.         -> heldMod  EXIT
  877.     THEN
  878.     
  879.     xdispl-offs
  880.     IF    xdispl-offs postpone literal
  881.         " ^base + dup @ +"  evaluate
  882.         offs IF                        \ will normally be zero
  883.                 offs postpone literal  " +" evaluate
  884.             THEN
  885.         cfa  bind_to_stk
  886.     ELSE
  887.         cfa offs  bind_to_ivar
  888.     THEN
  889. \    ?unholdMod  
  890.     -> heldMod
  891. ;
  892.  
  893.  
  894. \ OP/CL is common code factored out of objPtrRef and classRef, which
  895. \ are very similar.
  896.  
  897. : OP/CL  { selID ^class \ cfa offs xdispl-offs -- }
  898.  
  899.     selID
  900.     IF    selID ^class clFindm
  901.     ELSE
  902.         ^class  false  fix_pivar
  903.     THEN
  904.     -> xdispl-offs  -> offs  -> cfa
  905.  
  906.     xdispl-offs
  907.     IF    xdispl-offs postpone literal
  908.         " + dup @ +"  evaluate
  909.     THEN
  910.     
  911.     heldMod                    \ save
  912.     offs postpone literal  " +" evaluate
  913.     -> heldMod                \ restore
  914.     cfa bind_to_stk
  915. ;
  916.  
  917.  
  918. \ OBJPTRREF handles a reference to an object pointer.
  919.  
  920. : OBJPTRREF  { selID OP-cfa \ OPclass cfa offs xdispl-offs addr -- }
  921.  
  922.     OP-cfa  (comp)                    \ Compile a fetch of the OP-cfa,
  923.                                     \  giving ^obj at run time
  924.     OP-cfa >body  -> addr
  925.     addr 4+ @abs  -> OPclass
  926.     OPclass  0= ?error 86            \ "ObjPtr hasn't had a class specified"
  927.     OPclass hdlr $ BC2D =
  928.     IF                                \ Class is exported
  929.         OPclass 6 + wdisplace        \ Addr of module
  930.         compmod =  ?error 84        \ It's the module we're compiling -
  931.                                     \  this is a no-no, since the ObjPtr
  932.                                     \  reference will use the OLD module!
  933.         OPclass  ?>classInMod -> OPclass
  934.     THEN
  935.     selID OPclass  OP/cl
  936. ;
  937.  
  938. \ CLASSREF handles a reference to a class - this means use the object
  939. \  whose addr is on the stack, but ASSUME it is of the given class
  940. \  and early bind, without checking.
  941. \ The code is very similar to objPtrRef, naturally enough.
  942.  
  943. : CLASSREF { selID ^class \ cfa offs xdispl-offs -- }
  944.     need_class? IF  '  chkClass -> ^class  false -> need_class?  THEN
  945.     selID ^class  OP/cl
  946. ;
  947.  
  948.  
  949. \ TMPOBJREF handles a reference to a temp object.  The temp obj
  950. \  is set up as an ivar of class Dummy.
  951.  
  952. : TMPOBJREF  { selID ^ivar offs \ svHeldMod cfa xdispl-offs flags reg# -- }
  953.  
  954.     heldMod -> svHeldMod  0 -> heldMod
  955.     selID
  956.     IF    selID ^ivar ivFindM
  957.     ELSE
  958.         ^ivar 8 + @abs  false  fix_pivar
  959.     THEN
  960.     -> xdispl-offs  ++> offs  -> cfa
  961.  
  962.     xdispl-offs
  963.     IF    postpone locReg
  964.         xdispl-offs postpone literal  postpone +
  965.         postpone dup postpone @ postpone +
  966.         offs IF  offs postpone literal  postpone +  THEN    \ will normally be zero
  967.         cfa  bind_to_stk
  968.     ELSE
  969.                         \ is the temp object in a register?
  970.         ^ivar iffa w@  -> flags
  971.         flags 4 >> $ F and  ?dup
  972.         IF                        \ yes - we set the appropriate reg#
  973.                                 \  for the kind of reg we're binding to.
  974.             -> regcode_for_bind
  975.             flags 8 >> $ 1F and  -> reg_for_bind
  976.             cfa bind_to_reg
  977.         ELSE
  978.              cfa offs  bind_to_tmpObj
  979.          THEN
  980.         svHeldMod -> heldMod
  981.     THEN
  982. ;
  983.  
  984.  
  985. \ SuperRef handles the  msg: super> someSuper  construct.
  986.  
  987. : SUPERREF { selID \ ^nway namedClass ^nway' cnt -- }
  988.     ?class                            \ Must be compiling a class
  989.     '  -> namedClass                \ get named class xt
  990.     ^comp_class sfa -> ^nway
  991.     ^nway -> ^nway'  0 -> cnt
  992.     BEGIN
  993.         ^nway' @ 0= ?error 120            \ "superclass" not found
  994.         ^nway' @abs namedClass =
  995.     NWHILE
  996.         1cell ++> ^nway'  1 ++> cnt
  997.     REPEAT
  998.     cnt -> supers_to_skip
  999.     selID
  1000.     " SUPCL" sFind drop 46 +    \ careful of hard-coded number here
  1001.     $ FFFE  0  ivarRef            \ equivalent to msg: super
  1002. ;
  1003.  
  1004.  
  1005. forward COMPREF
  1006.  
  1007. \ PubIvarRef handles the  msg: ivar> someIvar IN someObj  construct, to
  1008. \  send a message directly to a public ivar in an object.  At this point
  1009. \  we've just read "ivar>".
  1010.  
  1011. : PUBIVARREF  { selID \ addr len ^class ^ivar -- }
  1012.     selID -> pivSel                    \ save selID being sent to the ivar
  1013.     mword hash  -> pivar            \ parse ivar name
  1014.     mword count  -> len  -> addr
  1015.     addr len  " IN" s=
  1016.     IF    0                 \ dummy "selID" for compRef (not a legal selector)
  1017.         compRef            \ handle whatever object comes after IN.  The
  1018.                         \  zero selector signals that a public ivar in the
  1019.                         \  indicated object is to be accessed - real selectors
  1020.                         \  can't ever be zero.  This will lead to fix_pivar
  1021.                         \  being called to complete the job.
  1022.     ELSE
  1023.         addr len " IN_CLASS" s=
  1024.         IF        public_static_ivar_ref
  1025.         ELSE    true ?error 194        \ "wrong syntax for public ivar"
  1026.         THEN
  1027.     THEN
  1028. ;
  1029.  
  1030.  
  1031. \ LBselfRef handles messages to [self] - i.e. late bound to Self.
  1032.  
  1033. : LBSELFREF  ( selID -- )
  1034.     " self" evaluate  postpone literal        \ pushes ^self, then selID
  1035.     postpone send
  1036. ;
  1037.  
  1038.  
  1039. \ Now here are the main words which compile the selector bindings.
  1040.  
  1041. \ CompRef operates at compile time - it compiles a selector bind.
  1042.  
  1043. :f COMPREF        \ ( selID -- )
  1044.  
  1045.     refToken    \ ( selID <various> type )
  1046.                 \    <various> will be the cfa of whatever came after the selector,
  1047.                 \    or ( offset ^ivar ) for ivars and temp objects (which are
  1048.                 \    treated as ivars of the class Dummy).
  1049.  
  1050.     CASE
  1051.         objTyp        OF  objRef                            ENDOF
  1052.         ivarTyp        OF    ivarRef                            ENDOF
  1053.         objPtrTyp    OF  objPtrRef                        ENDOF
  1054.         tmpObjTyp    OF  tmpObjRef                        ENDOF
  1055.         classTyp    OF    classRef                        ENDOF
  1056.  
  1057. \ These next 3 can only come up if implicit_late_bind? is true:
  1058. \        valTyp        OF  compdfr                            ENDOF
  1059. \        locTyp        OF  compdfr                            ENDOF
  1060. \        wordTyp        OF  compdfr                            ENDOF
  1061.  
  1062.         lbTyp        OF  drop  postpone literal
  1063.                         postpone send                    ENDOF
  1064.         lbSelfTyp    OF  drop  LBselfRef                    ENDOF
  1065.         bktTyp        OF  drop  -> dfrSelID  251            ENDOF
  1066.         superTyp    OF    drop  superRef                    ENDOF
  1067.         pubIvarTyp    OF    drop  pubIvarRef                ENDOF
  1068.  
  1069.         82 die                        \ "Selector can't be used on that"
  1070.         
  1071.     ENDCASE  ;f
  1072.  
  1073.  
  1074. (*
  1075. RunRef is the execution mode equivalent - it executes a selector bind.
  1076. We do this simply by compiling it in a buffer then executing it there.
  1077. The code is a bit like EX-GEN (see cg7).
  1078.  
  1079. While we're compiling in the buffer, we save CDP on the return stack,
  1080. then restore it before executing what we compiled (since it might do some
  1081. compiling itself).  This isn't long, but it's a bit tricky:
  1082. *)
  1083.  
  1084. : runRefBuf  ;                            \ never called, just ticked
  1085.                 256 code_reserve        \ allows 4 nested binds - worst case
  1086.                                         \  32 bytes each, we hope
  1087. 0    value        bufPtr
  1088. 0    value        hiCDP
  1089.  
  1090.  
  1091. : RUNREF  { selID \ svCDP svBufPtr svState svMC svMD -- }
  1092.  
  1093.     CDP -> svCDP                \ save DP
  1094.     CDP hiCDP umax -> hiCDP        \ so we can reset CDP to right place on an error
  1095.  
  1096.     bufPtr NIF  ['] runRefBuf 2-  ELSE  bufPtr  THEN
  1097.     dup -> CDP  -> svBufPtr    \ now we'll compile in runRefBuf
  1098.     state -> svState        \ save state
  1099. \    -1 -> state                \ need compile state so this compilation works properly
  1100.     :noname  drop            \ start a noname defn - drop security flag, leave xt
  1101.     selID compRef            \ compile the binding
  1102.     300  postpone ;            \ end noname defn, return to interpretation
  1103.     svState -> state        \ restore state
  1104.     0 -> hiCDP                \ don't need it any more and could cause problems
  1105. \    ?unholdMod
  1106.     CDP -> bufPtr            \ new bufPtr value
  1107. \    svBufPtr  CDP svBufPtr -  fix_caches
  1108.                             \ we're about to execute what we just compiled
  1109.     svCDP -> CDP            \ restore CDP since the code might compile something
  1110.  
  1111.     modCode -> svMC  modData -> svMD
  1112.     compmod
  1113.     IF    modcode_comp_start half_displ_range +  -> modCode
  1114.         moddata_comp_start half_displ_range +  -> modData
  1115.     THEN
  1116.  
  1117.     ( :noname xt )  execute            \ execute compiled code
  1118.  
  1119.     svMC -> modCode  svMD -> modData    \ restore module base addr regs
  1120.     svBufPtr -> bufPtr                    \ and old bufPtr
  1121. ;
  1122.  
  1123.  
  1124. \                ======== Selector support =========
  1125.  
  1126.  
  1127. \ MESSAGE is the handling word invoked by using a selector.
  1128.  
  1129. : MESSAGE        immed
  1130.     state
  1131.     IF                      \ Compile state
  1132.         compRef                \ Compile the message send
  1133. \        ?unHoldMod
  1134.     ELSE
  1135.         runRef                \ Run state - execute object/vector reference.
  1136.                             \ ?unHoldMod is called by ex-method at the
  1137.                             \ end, so we don't need to call it here.
  1138.     THEN  ;
  1139.  
  1140.  
  1141. (*
  1142. FIND will call the forward-defined initFind first, to attempt to find
  1143. a name.  So here we re-resolve initFind to lump together all the
  1144. special cases we have to look for after we've parsed an input word,
  1145. but before we can do a regular dictionary lookup.
  1146. At present these are selectors, named parms/locals, ivars
  1147. and local objects.  If we invent more later, they can easily be added.
  1148.  
  1149. If we succeed here, we return the selector ID or zero, the cfa of the 
  1150. handling word, and 1 or -1 (this will cause FIND to exit without doing
  1151. anything more).  If we fail, we return the original string address and
  1152. false.
  1153. *)
  1154.  
  1155. :f initFIND        \ ( str-addr -- selID message-cfa T  |  -- str-addr F )
  1156.     sel?                        \ is it a selector?
  1157.     IF        hash                \ yes - leave selID
  1158.             ['] message  1        \  and cfa of message, and 1 (it's immediate)
  1159.     ELSE    LocFind                \ no - look for the various kinds of local name
  1160.     THEN  ;f
  1161.  
  1162.  
  1163. \ ' 1stFind -> Ufind
  1164.  
  1165.  
  1166. : OBJLEN    \ ( -- objlen )  Computes total data length of current object.
  1167.  
  1168.     ^base (^dlen)  dup w@  swap 2+ w@  ?dup
  1169.     IF  idxBase 4- @ 1+  *  + 4+  THEN   ;
  1170.  
  1171.  
  1172.  
  1173. \ SET_CLASS should only be used internally in the Mops implementation.  It patches 
  1174. \  nucleus objects when their classes are defined in higher-level files.  Actually 
  1175. \  it could be used to change the class of any object, but that wouldn't be a very 
  1176. \  clever thing to do.
  1177.  
  1178. \ Usage:  fFcb  ['] file  set_class
  1179.  
  1180. : SET_CLASS  { ^obj theClass -- }
  1181.     theClass  chkClass  ^obj 8 -  reloc!        \ Patch ^class
  1182.     2  ^obj  2-  w!                    \ Not indexed (yet)
  1183.     -4 ^obj  4-  w!  ;                \ ^class offset
  1184.  
  1185.  
  1186. : CHKSAME        \ ( ^obj -- ^obj )
  1187.         \ A check that two objects are of exactly the
  1188.         \ same class.
  1189.     dup >classXt  ^base >classXt  <> ?error 87  ;
  1190.  
  1191.  
  1192.  
  1193.  
  1194. \            ========= Object pointers ==========
  1195.  
  1196. (*    Object pointers are low-level objects (like VALUEs) which point to a
  1197.     normal (high-level) object, and which allow early-bound messages to be
  1198.     sent to the object by syntactically sending them to the object pointer.
  1199.  
  1200.     The normal syntax is
  1201.  
  1202.     ObjPtr  ZZZ    class_is  someClass
  1203.  
  1204.     Thereafter, any messages sent to zzz are early-bound to the object that
  1205.     zzz points to at the time the message executes.
  1206.  
  1207.     If you need to declare the object pointer before the class exists, use
  1208.     SET_TO_CLASS once the class is defined, thus:
  1209.  
  1210.     :class  SOMECLASS    super{ object }
  1211.  
  1212.     ' someOP  set_to_class  someClass
  1213.  
  1214.     etc.
  1215. *)
  1216.  
  1217.  
  1218. :f  ToObjPtr
  1219.     state
  1220.     IF  litAddr_h  " (toOP)" evaluate  ELSE  >body (toOP)  THEN  ;f
  1221.  
  1222. \ Note: (toOP) is in qpClass.
  1223.  
  1224.  
  1225. : CLASS_IS    \ ( --< class > )
  1226.     ?exec  '  chkClass  DP 4-  reloc!  ;
  1227.  
  1228.  
  1229. : SET_TO_CLASS  { ^objPtr \ ^cl --< class > }
  1230.     '  -> ^cl
  1231.     ^objPtr hdlr $ BC1F <> ?error 85        \ "That isn't an ObjPtr"
  1232.  
  1233.             \ Now if "class" is an imported word, we change the handler code
  1234.             \ to "imported class".  This is normally done when the module
  1235.             \ is compiled, but it may not be yet, since we probably
  1236.             \ want to refer to the ObjPtr in the module.
  1237.  
  1238.     ^cl hdlr $ BD2E = IF  $ BC2D ^cl 2- w!  ELSE  ^cl chkClass drop  THEN
  1239.     ^cl  ^objPtr >body 4+  reloc!
  1240. ;
  1241.  
  1242.  
  1243. \        ===================================
  1244.  
  1245. \ Bytes is used as the allocation primitive for basic classes
  1246.  
  1247. : BYTES  { numBytes \ svRec? -- }
  1248.     ?class
  1249.     rec? -> svRec?  true -> rec?            \ Don't want an object header here
  1250.     " object" sFind drop  ivDef
  1251.     numBytes  ^comp_class dfa  w+!
  1252.     svRec? -> rec?  ;
  1253.  
  1254.  
  1255.  
  1256. (*        ================  Temp (local) objects  ===================
  1257.  
  1258. Syntax:
  1259.  
  1260. : aWord  { loc1 loc2 -- }        \ Locals are optional, of course
  1261.     temp
  1262.     {    var        v1
  1263.         int        i1
  1264.         string    s
  1265.     }
  1266.  
  1267.  Or you can use temp{ ...  } if you prefer.
  1268.  
  1269. As the syntax is quite similar to a list of ivars of a class, we actually
  1270. implement the temp objects as though they're the ivars of a dummy class
  1271. (which we uncreatively call Dummy).  This is just a convenience during
  1272. the compilation of a defn with temp objects.  It allows us to define them
  1273. and keep them visible during the compilation of the definition, while mainly
  1274. using existing code for ivar access.  We don't need these ivar dic entries
  1275. once the defn is finished, so we actually put them high in the dictionary
  1276. out of the way of the defn we're compiling.  At the end of the defn,
  1277. we reinitialize Dummy's ivar link ready for next time.
  1278. *)
  1279.  
  1280. getSelect release:            constant    releaseID
  1281.  
  1282.  
  1283. :class DUMMY  super{ object }
  1284. ;class
  1285.  
  1286. ' dummy ifa @    constant    dummyIfa
  1287.             \ ivar link corresponding to no ivars - it will be a relative
  1288.             \  pointer to the n-way for the superclass, and thus a constant
  1289.  
  1290. : RESETTEMPS
  1291.     dummyIfa  ['] dummy ifa  !
  1292.     0  ['] dummy dfa !                \ clear dlen and xwid
  1293.     0  ['] dummy ffa w!                \ and flags
  1294. ;
  1295.     
  1296.     \ Note we don't have to worry about the mfa since Dummy never gets
  1297.     \ its own methods.
  1298.  
  1299.  
  1300. (*    InitTemps is called when we're compiling the prologue for a definition
  1301.     with temp objects.  It compiles a call to make_obj for each object, so
  1302.     that they're properly initialized.  Note we can't just call make_obj once
  1303.     using class Dummy, since its ivar list is wiped out after each defn
  1304.     with temp objects, so at run time it won't have any!  But we don't need
  1305.     Dummy at run time anyway - we only need the "ivars" which are the
  1306.     temp objects themselves.
  1307. *)
  1308.  
  1309. :f INITTEMPS  { \ infa ^class flags reg# -- }
  1310.  
  1311.     ['] dummy ifa displace  -> infa
  1312.     BEGIN
  1313.         infa @ 0<
  1314.     WHILE
  1315.         infa ^iclass -> ^class
  1316.         infa iffa w@ -> flags
  1317.  
  1318.         flags 8 >> $ 1F and  dup -> reg#        \ register?
  1319.         IF                \ yes - we'll just clear the reg.  Not quite
  1320.                         \  classinit:, but better than nothing.
  1321.             flags 4 >> $ F and
  1322.             CASE  3  OF  \ $ 38000000  reg# 21 << or  ENDOF    \ rn  0        li,
  1323.                          0 reg#  lit>this_GPR
  1324.                      ENDOF
  1325.  
  1326.                   4  OF        $ FC007090  reg# 21 << or  code,    \ frn fr14    fmr,
  1327.                               reg#  mark_fpr_initialized
  1328.                        ENDOF
  1329.                   
  1330.                   5  OF            \ vec reg - we use vspltisw to splat zero
  1331.                          $ 10000000  908 or
  1332.                                     reg# 21 << or
  1333.                                     code,
  1334.                      ENDOF
  1335.             ENDCASE
  1336.  
  1337.         ELSE
  1338.             ^class xwid
  1339.             IF        \ it's indexed - we'll have #elements on the stack,
  1340.                     \  so we need to compile it as a literal for
  1341.                     \  make_obj to grab at run time.
  1342.                 infa i#els  postpone literal
  1343.             THEN
  1344.             
  1345.             ^class lit_addr
  1346.             infa ioffs  postpone literal
  1347.             postpone locreg  postpone +  postpone make_obj
  1348.         THEN
  1349.         infa ^nextivar  -> infa
  1350.     REPEAT  ;f
  1351.  
  1352.  
  1353. (*    ReleaseTemps is called from (;) in cg5 at the end of a definition.
  1354.     It compiles a release: xxx for all temp objects.  Because of the way
  1355.     we've defined release: in class Object, for simple objects no code will
  1356.     actually be generated.  
  1357.     
  1358.     Note we mustn't call resetTemps here since this might be an EXIT, not
  1359.     the final semicolon.  We leave calling resetTemps till a new temp{ comes
  1360.     up.
  1361. *)
  1362.  
  1363. :f RELEASETEMPS  { \ infa -- }
  1364.     ['] dummy ifa displace  -> infa
  1365.     BEGIN
  1366.         infa @ 0<
  1367.     WHILE
  1368.         infa ^iclass  0EXIT            \ shouldn't happen, actually
  1369.         releaseID  infa  ivFindM 2drop
  1370.         infa ioffs bind_to_tmpObj        \ compile release:
  1371.         infa ^nextivar  -> infa
  1372.     REPEAT
  1373. ;f
  1374.  
  1375.  
  1376. : }TEMP
  1377.     130 ?pairs
  1378.     ['] } >body !                        \ restore old action for "}"
  1379.     -> ^comp_class  -> cstate
  1380.     -> curr-def  -> CDP                    \ restore other things
  1381.  
  1382.     postpone ]                            \ start compiling
  1383.     0 -> basic_block_start  0 -> backstop_CDP
  1384.  
  1385.     tempObjs dlen -> tempObj_block_size        \ for cg3, so it will compile
  1386.                                             \  the right prolog
  1387.     true -> tempObjs?
  1388.     ['] dummy ffa w@ 8 >> $ F and  -> xalignment
  1389.                                 \ set any extra alignment we need for the frame
  1390.  
  1391.     local? NIF                    \ set up for entry unless we're in a local
  1392.                                 \  section (then it gets done by :LOC)
  1393.         PLentry
  1394.         <'> locreg 3+ c@  mark_gpr_initialized
  1395.                                 \ need to do this before we use it - which
  1396.                                 \  initTemps does!
  1397.         initTemps
  1398.     THEN
  1399.     ['] releaseTemps -> releaseTemps_xt
  1400.                         \ (;) compiles a call to there at semicolon time
  1401.     #PL4temps  -> #PL
  1402.     #FPL4temps -> #FPL
  1403.     #VL4temps  -> #VL
  1404. ;
  1405.  
  1406.  
  1407. : TEMP{        immed
  1408.  
  1409. (*    First we have to allocate an internal local variable as a frame pointer.
  1410.     There are 4 situations.  There may or may not already be locals, and
  1411.     we may or may not be in a local section.  Note we can be in a local
  1412.     section even if there aren't already locals, since the purpose of the
  1413.     local section might be just to establish a section for these temp objects.
  1414.  
  1415.     If there are already locals, we just add another.  If we're not in a
  1416.     local section we need to recompile the entry sequence (done by PLentry)
  1417.     since the number of regs to be saved and set up is different.  But if
  1418.     we're in a local section, we don't have to recompile since we haven't
  1419.     called PLentry yet, so we just add the extra local.  If there aren't any
  1420.     locals already, we just call initLocs which sets them up, before adding
  1421.     the new one.
  1422. *)
  1423.     resetTemps
  1424.     #PL #FPL or NIF  initLocs  THEN
  1425.                             \ No locs before, so weset up for them now
  1426.     #PL -> #PL4temps        \ We use these local copies since having
  1427.     #FPL -> #FPL4temps        \  compilation turned off and on clobbers
  1428.                             \  #PL and #FPL
  1429.     false -> leaf?            \ Our temp object frame stuff is quite
  1430.                             \  complicated, so we don't try to do leaf
  1431.                             \  optimization which wouldn't be worth it
  1432.                             \  anyway.
  1433.  
  1434.     local? IF  -1 -> local?  THEN    \ If in a local section, setting local?
  1435.                                     \ to -1 means we've defined the locals
  1436.                                     \ so can't do it again
  1437.     true -> locFlg                    \ it's a local, not a parm
  1438.     " x " pad place  pad addToParmList    \ pseudo local variable - name has
  1439.                                         \  a space so can't conflict
  1440.     32 #PL -                        \ this is the GPR# for the frame pointer
  1441.     dup -> TO_gpr#                    \ save it
  1442.     <'> locReg  3+ c!                \ and plug into locReg dic entry so 
  1443.                                     \  it identifies itself as the right reg
  1444.  
  1445. (*    Next we save CDP and move a long way up in the free dic space - we'll 
  1446.     put the "ivar dic entries" for the temp objs there - we don't need them
  1447.     after the defn is compiled.
  1448. *)
  1449.     CDP                $ 2000 ++> CDP  code_align
  1450.     curr-def
  1451.     cstate            true -> cstate
  1452.     ^comp_class
  1453.     ['] } >body @                \ save old action for "}"
  1454.     ['] }temp  -> }                \ "}" will now be same as }temp
  1455.     130                            \ for ?pairs
  1456.  
  1457.     ['] dummy dup    -> ^comp_class    \ local objs will look like ivars of Dummy
  1458.                     -> tempObjs        \ this will enable finding them
  1459.     postpone [                        \ stop compiling
  1460. ;
  1461.  
  1462.                             
  1463. : TEMP        gobble{  postpone temp{  ;        immediate
  1464.  
  1465. \ set_CD_gpr# sets the GPR we're going to use for this definition to
  1466. \  point to the start of the constant data.  We make it an internal
  1467. \  local variable, so the code is very similar to TEMP{ above.
  1468.  
  1469. :f set_CD_gpr#
  1470.  
  1471.     CD_gpr#  ?EXIT                    \ out if we've already done it
  1472.  
  1473.     #PL #FPL or NIF  initLocs  THEN        
  1474.                                     \ No locs before, so set up for them now
  1475.  
  1476.     local? IF  -1 -> local?  THEN    \ If in a local section, setting local?
  1477.                                     \ to -1 means we've defined the locals
  1478.                                     \ so can't do it again
  1479.     true -> locFlg                    \ it's a local, not a parm
  1480.     " q " pad place  pad addToParmList
  1481.                                     \ pseudo local variable - name has
  1482.                                     \  a space so can't conflict
  1483.     32 #PL -                \ this is the GPR# for the const data pointer
  1484.     dup -> CD_gpr#
  1485.     select: GPRs  permanent: GPRs
  1486.     #PL -> #PL4temps        \ may be needed for register temp objects
  1487. ;f
  1488.  
  1489.  
  1490. \        =================  register temp objects ====================
  1491.  
  1492. (*
  1493. A temp object can be specified to be instantiated in a register
  1494. if possible, by putting "register" before its declaration (a bit
  1495. like C).
  1496.  
  1497. Any methods called on a register temp object must be inline, which
  1498. makes sense, since non-inline methods need the address of the object
  1499. in the obj base register (r20), and objects in a register don't have
  1500. an address!  Also, of course, the object must have a length less
  1501. than or equal to that of the register.
  1502.  
  1503. If we can't meet a register request, that isn't necessarily an error.  A
  1504. user might optimistically put "register" on an object whose class can't
  1505. go in a register, or we might just not have enough registers, but as that
  1506. doesn't affect the results, we don't call it an error.
  1507.  
  1508. But if the object is indexed, or bigger than the register, that's probably
  1509. a Mops bug since we should never use can_be_gpr etc. on those classes.
  1510. Or maybe the user has wrongly used can_be_gpr.  So we give an error for 
  1511. those.
  1512. *)
  1513.  
  1514. : REGISTER
  1515.     cstate NIF  222 die  THEN        \ "A register object must be a temp object"
  1516.     true -> register_request?  ;
  1517.  
  1518.  
  1519. :f REGISTER_CHECK  { ^class ivflags \ regcode ivLength -- ivflags' }
  1520.  
  1521.     register_request? NIF  ivflags  EXIT  THEN
  1522.     false -> register_request?        \ for next time
  1523.  
  1524.     ^class ffa w@ 4 >> $ F and  -> regcode
  1525.     regcode NIF  ivflags  EXIT  THEN        \ that class doesn't have can_be_gpr
  1526.                                             \  or whatever specified.  We don't
  1527.                                             \  call this an error.
  1528.  
  1529.     ^class dlen&xwid
  1530.     IF  223 die  THEN        \ "indexed object can't be in a register"
  1531.  
  1532.     regcode
  1533.     CASE 
  1534.         3 OF            \ check if we can get a gpr
  1535.             4 > IF  224 die  THEN
  1536.             #PL4temps  maxPL <
  1537.             IF
  1538.                 1 ++> #PL4temps
  1539.                 32 #PL4temps -        \ this is the GPR#
  1540.                 4 << 3 or 4 <<  or> ivflags
  1541.             THEN
  1542.         ENDOF
  1543.         
  1544.         4 OF            \ check if we can get an fpr
  1545.             8 > IF  224 die  THEN
  1546.              #FPL4temps  maxFPL <
  1547.              IF
  1548.                  1 ++> #FPL4temps
  1549.                  32 #FPL4temps -
  1550.                  4 << 4 or 4 <<  or> ivflags
  1551.              THEN
  1552.          ENDOF
  1553.  
  1554.         5 OF            \ check if we can get a vr
  1555.             16 > IF  224 die  THEN
  1556.              #VL4temps  maxVL <
  1557.              IF
  1558.                  1 ++> #VL4temps
  1559.                  32 #VL4temps -
  1560.                  4 << 5 or 4 <<  or> ivflags
  1561.              THEN
  1562.          ENDOF
  1563.  
  1564.     ENDCASE
  1565.          
  1566.     ivflags
  1567. ;f
  1568.  
  1569.  
  1570. (* ***
  1571. \ testing temp objects with indexing:
  1572. +echo
  1573.  
  1574. : q
  1575. temp{    10 array aa
  1576.         5  array bb
  1577. }
  1578.  
  1579.     5 at: aa  4 to: bb
  1580. ;
  1581.  
  1582. : qq db q ;
  1583.  
  1584. endload
  1585. *)
  1586.  
  1587.  
  1588. (*        =================  Records and unions  ====================
  1589.  
  1590. Syntax:
  1591.  
  1592.     record <name>        \ The name is optional
  1593.    {    var        v1
  1594.         int        i1
  1595.         string    s
  1596.    }
  1597.    
  1598.        union <name>        \ The name is optional
  1599.    {    var        v1
  1600.         int        i1
  1601.         string    s
  1602.    }
  1603.  
  1604.  
  1605. Or you can use record{ ...  } or union{ ... } if you prefer, if it's
  1606. unnamed.  The similarity of syntax to temp objects is quite deliberate.
  1607. But any similarity to Your Favorite Language is entirely accidental.  Well
  1608. actually it's not, but I think this syntax is as good as any, and probably
  1609. more readable for folks coming from the land of C.
  1610.  
  1611. unions can be nested within records and vice versa.
  1612.  
  1613. NOTE: it's best to not use unions unless you're really sure you know what
  1614. you're doing.  Having different objects sharing the same memory is sure
  1615. to cause problems if you're careless!
  1616.  
  1617. *)
  1618.  
  1619. : SVREC        
  1620.     ^comp_class dfa w@ 
  1621.     rec?  union?  unionOffs  68k_align?
  1622. ;
  1623.  
  1624. : RSTREC
  1625.     -> 68k_align?  -> unionOffs  -> union?  -> rec?  
  1626.     union? IF     \ we fell back in a union, so we
  1627.                 \ reset data pointer to where it was at the beginning
  1628.                 \ of this union/rec
  1629.         ^comp_class dfa w!
  1630.     ELSE
  1631.         drop
  1632.     THEN
  1633. ;
  1634.  
  1635. : ?HANDLE_NAME  { \ sv_>in sv_^class sv_rec? -- }
  1636.     >in @ -> sv_>in ^comp_class -> sv_^class  rec? -> sv_rec?
  1637.     Mword  count  " {" s=
  1638.     NIF                            \ we've got a name for the record
  1639.         true -> rec?            \ must do this before defining the name "object"
  1640.         sv_>in  >in !
  1641.         " object" sFind drop  ivDef
  1642.         sv_rec? -> rec?  sv_^class -> ^comp_class
  1643.         gobble{                    \ "{" must follow
  1644.     THEN
  1645. ;
  1646.  
  1647.  
  1648. : }RECORD
  1649.     131 ?pairs  rstRec
  1650.     ['] } >body !  ;
  1651.  
  1652.  
  1653. : RECORD{
  1654.     ?class                        \ must be compiling a class
  1655.     ['] } >body @                \ save old action for "}"
  1656.     ['] }record  -> }            \ "}" will now be same as }record
  1657.     svRec                        \ save parameters for any existing record/union
  1658.     131                            \ for ?pairs
  1659.     true -> rec?  false -> union?  ;
  1660.  
  1661. : RECORD
  1662.     ?handle_name
  1663.     record{  ;
  1664.  
  1665. : 68k_RECORD{
  1666.     record{
  1667.     true -> 68k_align?  ;
  1668.  
  1669. : 68k_RECORD
  1670.     record
  1671.     true -> 68k_align?  ;
  1672.  
  1673.  
  1674. : }UNION
  1675.     132 ?pairs
  1676.     unionOffs  ^comp_class dfa w!    
  1677.     rstRec
  1678.     ['] } >body !  ;            \ restore old action for "}"
  1679.  
  1680. : UNION{
  1681.     ?class                        \ must be compiling a class
  1682.     ['] } >body @                \ save old action for "}"
  1683.     ['] }union  -> }            \ "}" will now be same as }union
  1684.     svRec                        \ save record/union parameters
  1685.     132                            \ for ?pairs
  1686.     true -> rec?  true -> union?
  1687.     ^comp_class dfa w@ -> unionOffs  ;
  1688.  
  1689.  
  1690. : UNION
  1691.     ?handle_name
  1692.     union{  ;
  1693.  
  1694. (*        =================  Static ivars ====================
  1695.  
  1696. Syntax:
  1697.  
  1698.     static
  1699.    {    var        v1
  1700.         int        i1
  1701.         string    s
  1702.    }
  1703.  
  1704. Or you can use  static{ ...  } if you prefer.
  1705.  
  1706. These are like static class variables in C++ - they belong to the class,
  1707. not the object, and thus are shared by all objects of the class.  We
  1708. allocate each ivar in the dictionary right after its ivar header.
  1709. *)
  1710.  
  1711. : }STATIC
  1712.     133 ?pairs
  1713.     ['] } >body !                    \ restore old action for "}"
  1714.     false -> static?  ;
  1715.  
  1716.  
  1717. : STATIC{
  1718.     ?class                        \ must be compiling a class
  1719.     ['] } >body @                    \ save old action for "}"
  1720.     ['] }static  -> }            \ "}" will now be same as }static
  1721.     133                            \ for ?pairs
  1722.     true -> static?  ;
  1723.  
  1724. : STATIC
  1725.     gobble{  static{  ;
  1726.  
  1727.  
  1728. \        ===================================================
  1729.  
  1730.  
  1731. (*    CL1 is our first stage cleanup word - called on an abort.  Resets things
  1732.     to normal.  Later cleanup words do their special stuff, then call CL1.
  1733.     Actually on the PPC it's not quite the first, since we've loaded pFiles
  1734.     already, and so have already introduced clFiles as the file cleanup
  1735.     word.  On the 68k it was really the first.
  1736. *)
  1737.  
  1738. : CL1
  1739.     (;cl)  clrComp  ['] (}) -> }
  1740.     0 -> bufPtr  0 -> hiCDP        \ for interpreting message binds
  1741.     resetTemps
  1742.     false -> rec?  false -> union?
  1743.     false -> 68k_align?  false -> compinline?
  1744.     false -> bind_to_reg?
  1745.     0 -> extraFind
  1746.     0 -> bufPtr
  1747.     false -> case_in_names?
  1748.     clFiles
  1749. ;
  1750.  
  1751. ' cl1  -> abortVec
  1752.  
  1753.  
  1754. torture? not [IF]  endload  [THEN]
  1755.  
  1756.  
  1757. (* ***********
  1758.  
  1759. \ A simple test of the basic class stuff - run if the plot
  1760. \  gets totally lost:
  1761.  
  1762. :class nothingClass super{ object }
  1763. ;class
  1764.  
  1765. :class testClass super{ object }
  1766. :m aa: 1 2 3 ;m
  1767. :m bb: 99  aa: self  ;m
  1768. ;class
  1769.  
  1770. testClass ttt
  1771. bb: ttt            \ should leave ( -- 1 2 3 99 )
  1772.  
  1773.  
  1774. :class cl2 super{ testClass }
  1775.   testClass bloggs
  1776. :m cc:  $ 1234
  1777.         bb: bloggs
  1778.         bb: super
  1779. ;m
  1780. ;class
  1781.  
  1782. cl2  myObj
  1783. cc: myObj
  1784.  
  1785.  
  1786. ********** *)
  1787.  
  1788. \ ===============================================================
  1789. \                        TORTURE TESTS
  1790. \ ===============================================================
  1791.  
  1792.  
  1793. : ?CHK
  1794.     2dup <>
  1795.     IF    cr .h cr .h
  1796.         true abort" check FAILED!!!"        \ error if something doesn't
  1797.                                             \  give what we expect
  1798.     ELSE
  1799.         2drop
  1800.     THEN
  1801. ;
  1802.  
  1803. \ working on new temp object stuff here:
  1804.  
  1805.  
  1806. (* ***** *)
  1807.  
  1808. :class    VAR    super{ object }  can_be_gpr
  1809.  
  1810.     4 bytes data
  1811.  
  1812. :m CLEAR:    inline{ 0 ^base !}  ;m
  1813.  
  1814. :m GET:        inline{ ^base @}  ;m
  1815.  
  1816. :m PUT:        inline{ ^base !}  ;m
  1817.  
  1818. :m +:        inline{ ^base @ + ^base !}  ;m
  1819.  
  1820. :m ->:        inline{ @ ^base !}  ;m
  1821.  
  1822. :m classinit:  db 123  ^base !  ;m
  1823.  
  1824. ;class
  1825.  
  1826. :class    INT    super{ object }  can_be_gpr
  1827.  
  1828.     2 bytes data
  1829.  
  1830. :m CLEAR:    inline{ 0 ^base w!}  ;m
  1831.  
  1832. :m GET:        inline{ ^base w@}  ;m
  1833.  
  1834. :m PUT:        inline{ ^base w!}  ;m
  1835.  
  1836. :m +:        inline{ ^base w@ + ^base w!}  ;m
  1837.  
  1838. :m ->:        inline{ w@ ^base w!}  ;m
  1839.  
  1840. :m classinit:  db 123  ^base !  ;m
  1841.  
  1842. ;class
  1843.  
  1844.  
  1845. :class    BYTE    super{ object }  can_be_gpr
  1846.  
  1847.     1 bytes data
  1848.  
  1849. :m CLEAR:
  1850.     inline{ 0 ^base c!}  ;m
  1851.  
  1852. :m GET:
  1853.     inline{ ^base c@x}  ;m
  1854.  
  1855. :m UGET:
  1856.     inline{ ^base c@}  ;m
  1857.  
  1858. :m PUT:
  1859.     inline{ ^base c!}  ;m
  1860.  
  1861. :m ->:
  1862.     inline{ c@ ^base c!}  ;m
  1863.  
  1864. :m PRINT:
  1865.     ^base c@  .        ;m
  1866.  
  1867. :m CLASSINIT:    9 put: self  ;m
  1868.  
  1869. ;class
  1870.  
  1871.  
  1872. :class    BOOL    super{ byte }  can_be_gpr
  1873.  
  1874. :m GET:
  1875.     inline{ ^base c@x}  ;m
  1876.  
  1877. :m PUT:
  1878.     inline{ 0<> ^base c!}  ;m
  1879.  
  1880. :m SET:
  1881.     inline{ true ^base c!}  ;m
  1882.  
  1883. :m PRINT:
  1884.     get: self  IF  ." true"  ELSE  ." false"  THEN  ;m
  1885.  
  1886. :m CLASSINIT:    clear: self  ;m
  1887.  
  1888. ;class
  1889.  
  1890.  
  1891. :class  FLOAT  super{ object }  can_be_fpr  3 alignment
  1892.  
  1893. 8    bytes    data
  1894.  
  1895. :m GET:        \ ( -- x )    Pushes private data onto FP stack
  1896.     inline{ ^base f@}  ;m
  1897.  
  1898. :m PUT:        \ ( x -- )  Stores float into private data
  1899.     inline{ ^base f!}  ;m
  1900.  
  1901. :m ->:        \ ( float -- )  Assigns value of passed-in Float to this Float
  1902.     inline{ f@ ^base f!}  ;m
  1903.  
  1904.  
  1905. \ Normal arithmetic operations take a float on the FP stack.
  1906. \  Methods starting with by obj_ take a Float object address.
  1907. \  Methods ending with ->: take 2 Float object addresses and
  1908. \  store the result in this object.
  1909.  
  1910. :m +:
  1911.     inline{ ^base f@ f+ ^base f!}  ;m
  1912.  
  1913. :m obj_+:
  1914.     inline{ f@ ^base f@ f+ ^base f!}  ;m
  1915.  
  1916. :m +->:
  1917.     inline{ f@ f@ f+ ^base f!}  ;m
  1918.  
  1919.  
  1920. :m -:
  1921.     inline{ ^base f@ fswap f- ^base f!}  ;m
  1922.  
  1923. :m obj_-:
  1924.     inline{ ^base f@ f@ f- ^base f!}  ;m
  1925.  
  1926. :m -->:
  1927.     inline{ f@ f@ fswap f- ^base f!}  ;m
  1928.  
  1929.  
  1930. :m *:
  1931.     inline{ ^base f@ f* ^base f!}  ;m
  1932.  
  1933. :m obj_*:
  1934.     inline{ f@ ^base f@ f* ^base f!}  ;m
  1935.  
  1936. :m *->:
  1937.     inline{ f@ f@ f* ^base f!}  ;m
  1938.  
  1939.  
  1940. :m /:
  1941.     inline{ ^base f@ fswap f/ ^base f!}  ;m
  1942.  
  1943. :m obj_/:
  1944.     inline{ ^base f@ f@ f/ ^base f!}  ;m
  1945.  
  1946. :m /->:
  1947.     inline{ f@ f@ fswap f/ ^base f!}  ;m
  1948.  
  1949. :m test:    ^base 8 dump  ;m
  1950.  
  1951. ;class
  1952.  
  1953.  
  1954. : __v3op        hex intrp1 intrp1 decimal false  (vop)  ;    immediate
  1955. : __v2op        postpone tuck  postpone __v3op  ;            immediate
  1956. : __v4op        hex intrp1 intrp1 decimal true  (vop)  ;    immediate
  1957.  
  1958.  
  1959. :class  WORD_VECTOR  super{ object }  can_be_vr  4 alignment
  1960.  
  1961. 16    bytes    data
  1962.  
  1963. :m +:        inline{ ^base __v2op 21 2 }    ;m
  1964. :m +->:        inline{ ^base __v3op 21 2 }    ;m
  1965. :m -:        inline{ ^base __v2op 22 2 }    ;m
  1966. :m -->:        inline{ ^base __v3op 22 2 }    ;m
  1967.  
  1968. :m and:        inline{ ^base __v2op 23 0 }    ;m
  1969. :m or:        inline{ ^base __v2op 24 0 }    ;m
  1970. :m xor:        inline{ ^base __v2op 25 0 }    ;m
  1971.  
  1972. :m and->:    inline{ ^base __v3op 23 0 }    ;m
  1973. :m or->:    inline{ ^base __v3op 24 0 }    ;m
  1974. :m xor->:    inline{ ^base __v3op 25 0 }    ;m
  1975.  
  1976. :m ->:        inline{ dup ^base __v3op 24 2 }    ;m
  1977. :m splat:    inline{ ^base __v3op 80 2 }        ;m
  1978. :m Nsplat:    inline{ dup ^base __v3op 81 2 }    ;m
  1979.  
  1980. :m select:    inline{ ^base __v4op 90 0 }        ;m
  1981. :m permute:    inline{ ^base __v4op 91 0 }        ;m
  1982.  
  1983. :m AT:  ( index -- n )
  1984.     4* ^base + @  ;m
  1985.  
  1986. :m TO:  ( n index -- )
  1987.     4* ^base + !  ;m
  1988.  
  1989. :m GET:        \ ( -- n1..n4 )
  1990.     4 0 DO  ^base i 4* +  @  LOOP
  1991. ;m
  1992.  
  1993. :m PUT:        \ ( n1..n4 -- )
  1994.     4 FOR  ^base i 4* +  !  NEXT
  1995. ;m
  1996.  
  1997.  
  1998. :m classinit:
  1999.     4 FOR  i  ^base i 4* +  !  NEXT
  2000. ;m
  2001.  
  2002. ;class
  2003.  
  2004. :class  UWORD_VECTOR  super{ word_vector }  can_be_vr  4 alignment
  2005.  
  2006. :m +:        inline{ ^base __v2op 21 42 }  ;m
  2007. :m +->:        inline{ ^base __v3op 21 42 }  ;m
  2008. :m -:        inline{ ^base __v2op 22 42 }  ;m
  2009. :m -->:        inline{ ^base __v3op 22 42 }  ;m
  2010.  
  2011. ;class
  2012.  
  2013. :class  SWORD_VECTOR  super{ word_vector }  can_be_vr  4 alignment
  2014.  
  2015. :m +:        inline{ ^base __v2op 21 C2 }  ;m
  2016. :m +->:        inline{ ^base __v3op 21 C2 }  ;m
  2017. :m -:        inline{ ^base __v2op 22 C2 }  ;m
  2018. :m -->:        inline{ ^base __v3op 22 C2 }  ;m
  2019.  
  2020. :m Nsplat:    inline{ dup ^base __v3op 81 C2 }    ;m
  2021.  
  2022. ;class
  2023.  
  2024.  
  2025. :class  INT_VECTOR  super{ word_vector }  can_be_vr  4 alignment
  2026.  
  2027. :m PUT:        \ ( n1..n16 -- )
  2028.     8 FOR  ^base i 2* +  w!  NEXT
  2029. ;m
  2030.  
  2031. :m +:        inline{ ^base __v2op 21 1 }  ;m
  2032. :m +->:        inline{ ^base __v3op 21 1 }  ;m
  2033. :m -:        inline{ ^base __v2op 22 1 }  ;m
  2034. :m -->:        inline{ ^base __v3op 22 1 }  ;m
  2035. :m ->:        inline{ dup ^base __v3op 24 1 }    ;m
  2036. :m splat:    inline{ ^base __v3op 80 1 }        ;m
  2037. :m Nsplat:    inline{ dup ^base __v3op 81 1 }    ;m
  2038.  
  2039. :m classinit:
  2040.     4 FOR  i  ^base i 4* +  !  NEXT
  2041. ;m
  2042.  
  2043. ;class
  2044.  
  2045. :class  UINT_VECTOR  super{ int_vector }  can_be_vr  4 alignment
  2046.  
  2047. :m +:        inline{ ^base __v2op 21 41 }  ;m
  2048. :m +->:        inline{ ^base __v3op 21 41 }  ;m
  2049. :m -:        inline{ ^base __v2op 22 41 }  ;m
  2050. :m -->:        inline{ ^base __v3op 22 41 }  ;m
  2051.  
  2052. :m *:        inline{ ^base __v2op 12 41 }  ;m
  2053. :m *h:        inline{ ^base __v2op 10 41 }  ;m
  2054. :m *->:        inline{ ^base __v3op 12 41 }  ;m
  2055. :m *h->:    inline{ ^base __v3op 10 41 }  ;m
  2056.  
  2057.  
  2058. ;class
  2059.  
  2060. :class  SINT_VECTOR  super{ word_vector }  can_be_vr  4 alignment
  2061.  
  2062. :m +:        inline{ ^base __v2op 21 C2 }  ;m
  2063. :m +->:        inline{ ^base __v3op 21 C2 }  ;m
  2064. :m -:        inline{ ^base __v2op 22 C2 }  ;m
  2065. :m -->:        inline{ ^base __v3op 22 C2 }  ;m
  2066.  
  2067. :m *:        inline{ ^base __v2op 12 C1 }  ;m
  2068. :m *h:        inline{ ^base __v2op 10 C1 }  ;m
  2069. :m *->:        inline{ ^base __v3op 12 C1 }  ;m
  2070. :m *h->:    inline{ ^base __v3op 10 C1 }  ;m
  2071.  
  2072. :m Nsplat:    inline{ dup ^base __v3op 81 C1 }    ;m
  2073.  
  2074. ;class
  2075.  
  2076. :class  BYTE_VECTOR  super{ word_vector }  can_be_vr  4 alignment
  2077.  
  2078. :m PUT:        \ ( n1..n16 -- )
  2079.     16 FOR  ^base i +  c!  NEXT
  2080. ;m
  2081.  
  2082. :m +:        inline{ ^base __v2op 21 0 }  ;m
  2083. :m +->:        inline{ ^base __v3op 21 0 }  ;m        \ 2 operand vectors
  2084. :m -:        inline{ ^base __v2op 22 0 }  ;m
  2085. :m -->:        inline{ ^base __v3op 22 0 }  ;m        \ 2 operand vectors
  2086.  
  2087. :m ->:        inline{ dup ^base __v3op 24 0 }    ;m
  2088. :m splat:    inline{ ^base __v3op 80 0 }        ;m
  2089. :m Nsplat:    inline{ dup ^base __v3op 81 0 }    ;m
  2090.  
  2091. :m classinit:
  2092.     16 FOR  i  ^base i 2* +  w!  NEXT
  2093. ;m
  2094.  
  2095. ;class
  2096.  
  2097.  
  2098. :class  UBYTE_VECTOR  super{ byte_vector }  can_be_vr  4 alignment
  2099.  
  2100. :m +:        inline{ ^base __v2op 21 40 }  ;m
  2101. :m +->:        inline{ ^base __v3op 21 40 }  ;m
  2102. :m -:        inline{ ^base __v2op 22 40 }  ;m
  2103. :m -->:        inline{ ^base __v3op 22 40 }  ;m
  2104.  
  2105. :m *:        inline{ ^base __v2op 12 40 }  ;m
  2106. :m *h:        inline{ ^base __v2op 10 40 }  ;m
  2107. :m *->:        inline{ ^base __v3op 12 40 }  ;m
  2108. :m *h->:    inline{ ^base __v3op 10 40 }  ;m
  2109.  
  2110. ;class
  2111.  
  2112. :class  SBYTE_VECTOR  super{ byte_vector }  can_be_vr  4 alignment
  2113.  
  2114. :m +:        inline{ ^base __v2op 21 C0 }  ;m
  2115. :m +->:        inline{ ^base __v3op 21 C0 }  ;m
  2116. :m -:        inline{ ^base __v2op 22 C0 }  ;m
  2117. :m -->:        inline{ ^base __v3op 22 C0 }  ;m
  2118.  
  2119. :m *:        inline{ ^base __v2op 12 C0 }  ;m
  2120. :m *h:        inline{ ^base __v2op 10 C0 }  ;m
  2121. :m *->:        inline{ ^base __v3op 12 C0 }  ;m
  2122. :m *h->:    inline{ ^base __v3op 10 C0 }  ;m
  2123.  
  2124. :m Nsplat:    inline{ dup ^base __v3op 81 C0 }    ;m
  2125.  
  2126. ;class
  2127.  
  2128. :class  FLOAT_VECTOR  super{ object }  can_be_vr  4 alignment
  2129.  
  2130. 16    bytes    data
  2131.  
  2132. :m +:        inline{ ^base __v2op 41 3 }  ;m
  2133. :m +->:        inline{ ^base __v3op 41 3 }  ;m
  2134. :m -:        inline{ ^base __v2op 48 3 }  ;m
  2135. :m -->:        inline{ ^base __v3op 48 3 }  ;m
  2136.  
  2137. :m *+:        inline{ ^base dup __v4op 43 3 }  ;m
  2138. :m *+->:    inline{ ^base __v4op 43 3 }  ;m
  2139.  
  2140. :m ->:        inline{ dup ^base __v3op 24 2 }    ;m
  2141. :m select:    inline{ ^base __v4op 90 0 }        ;m
  2142. :m permute:    inline{ ^base __v4op 91 0 }        ;m
  2143.  
  2144. :m AT:  ( index -- n )
  2145.     4* ^base + sf@  ;m
  2146.  
  2147. :m TO:  ( n index -- )
  2148.     4* ^base + sf!  ;m
  2149.  
  2150. :m GET:        \ ( -- n1..n4 )
  2151.     4 0 DO  ^base i 4* +  sf@  LOOP
  2152. ;m
  2153.  
  2154. :m PUT:        \ ( n1..n4 -- )
  2155.     4 FOR  ^base i 4* +  sf!  NEXT
  2156. ;m
  2157.  
  2158. ;class
  2159.  
  2160.  
  2161. +echo
  2162.  
  2163. int_vector vv3
  2164. int_vector vv4
  2165.  
  2166. : q  { \ %aa %bb -- }
  2167.     temp{
  2168.             register byte_vector vb1
  2169.             register sbyte_vector vb2
  2170.             register ubyte_vector vb3
  2171.             register sbyte_vector vb4
  2172.  
  2173.             register int_vector vi1
  2174.             register sint_vector vi2
  2175.             register uint_vector vi3
  2176.             
  2177.             register uword_vector uvw1
  2178.             register sword_vector vw1
  2179.             register sword_vector vw2
  2180.             
  2181.             register float_vector fv1
  2182.             register float_vector fv2
  2183.             register float_vector fv3
  2184.  
  2185.             register float    f1
  2186.             register float    f2
  2187.             register float    f3
  2188. }
  2189.     vb2 -: vb1
  2190.     f2 obj_-: f1
  2191.     f2 f3 -->: f1
  2192.     5 Nsplat: uvw1
  2193.     -3 Nsplat: vi2
  2194.     vi1 2 splat: vi3
  2195.     vb1 10 splat: vb2
  2196.     vb1 vb2 vb3 permute: vb4
  2197.     fv1 fv2 *+: fv3
  2198. ;
  2199.  
  2200. : qq db q ;
  2201. endload
  2202.  
  2203. ***** *)
  2204.  
  2205.  
  2206. :class    VAR    super{ object }
  2207.  
  2208.     4 bytes data
  2209.  
  2210. :m CLEAR:
  2211.     inline{ 0 ^base !}  ;m
  2212.  
  2213. :m GET:
  2214.     inline{ ^base @}  ;m
  2215.  
  2216. :m PUT:
  2217.     inline{ ^base !}  ;m
  2218.  
  2219. :m GETT:    ^base @  ;m
  2220.     
  2221. :m PUTT:    ^base !  ;m
  2222.  
  2223. :m +:
  2224.     inline{ ^base +!}  ;m
  2225.  
  2226. :m -:
  2227.     inline{ ^base -!}  ;m
  2228.  
  2229. :m ->:
  2230.     inline{ @ ^base !}  ;m
  2231.  
  2232. :m TEST:  @ ^base !  ;m
  2233.  
  2234. mlocal LOCTEST:  { aa \ bb cc -- }
  2235.  
  2236. :m AAA:    aa -> bb  ;m
  2237.  
  2238. :mloc  LOCTEST:        \ should double the number passed in and store in self
  2239.     aaa: self        \ ." loctest: here!" cr
  2240.     bb -> cc  bb ++> cc
  2241.     cc  ^base !
  2242. ;mloc
  2243.  
  2244. mlocal LOCTEST2:  { aa bb cc dd ee ff \ gg hh ii -- }
  2245.  
  2246. :m bbb:
  2247.     aa bb +  cc *  -> gg
  2248.     dd ee +  ff *  -> hh
  2249.     gg hh +  -> ii
  2250.     " hi there"
  2251. ;m
  2252.  
  2253. :mloc  loctest2:
  2254.     bbb: self  ii ^base !
  2255.     " ho ho"
  2256. ;mloc
  2257.  
  2258.     
  2259. :m PRINT:
  2260.     ^base @  .  ;m
  2261.  
  2262. :m CLASSINIT:
  2263.     $ 123  put: self  ;m
  2264.  
  2265. ;class
  2266.  
  2267.  
  2268. :class    BYTE    super{ object }
  2269.  
  2270.     1 bytes data
  2271.  
  2272. :m CLEAR:
  2273.     inline{ 0 ^base c!}  ;m
  2274.  
  2275. :m GET:
  2276.     inline{ ^base c@x}  ;m
  2277.  
  2278. :m UGET:
  2279.     inline{ ^base c@}  ;m
  2280.  
  2281. :m PUT:
  2282.     inline{ ^base c!}  ;m
  2283.  
  2284. :m ->:
  2285.     inline{ c@ ^base c!}  ;m
  2286.  
  2287. :m PRINT:
  2288.     ^base c@  .        ;m
  2289.  
  2290. :m CLASSINIT:    9 put: self  ;m
  2291.  
  2292. ;class
  2293.  
  2294. \ some very simple testing, to start with:
  2295.  
  2296. 0        value    testVal
  2297.  
  2298.         var        aVar
  2299.         byte    aByte
  2300.  
  2301. : test1
  2302. ." test1" cr
  2303.     987 avar !  get: avar  987 ?chk            \ optimizes
  2304.     addr: avar  -> testVal
  2305.     876 testVal !                            \ should clobber opt
  2306.     get: avar  876  ?chk
  2307. ;
  2308.  
  2309. : test2            \ testing late binding - assumes test1 done
  2310. ." test2" cr
  2311.     get: [ avar ]  876  ?chk
  2312. \ now, does the late-bind cache work?
  2313.     get: [ avar ]  876  ?chk
  2314. ;
  2315.  
  2316.  
  2317. local  localTest { \ aa bb cc dd -- }
  2318.  
  2319. : aaa    " hahaha"  ;
  2320.  
  2321. :loc localTest
  2322.         aaa  " hoho"
  2323. ;loc
  2324.  
  2325.  
  2326. : test3            \ testing local methods, and local sections with const
  2327.                 \  data.  Note: we can assume ordinary local sections
  2328.                 \  work, since we use them in the class stuff so we wouldn't
  2329.                 \  have made it to here unless they work!!
  2330. ." test3" cr
  2331.     222 loctest: aVar  get: aVar  444 ?chk
  2332.     20 30 3            \ -> 150
  2333.     10 30 4            \ -> 160
  2334.     loctest2: aVar  get: aVar 310 ?chk
  2335.     " ho ho" s=    -1 ?chk
  2336.     " hi there" s= -1 ?chk
  2337.     localtest    " hoho" s=  -1 ?chk
  2338.                 " hahaha" s=  -1 ?chk
  2339. ;
  2340.  
  2341.  
  2342. var vv
  2343.  
  2344. :class    BOOL    super{ byte }
  2345.  
  2346. :m GET:
  2347.     inline{ ^base c@x}  ;m
  2348.  
  2349. :m PUT:
  2350.     inline{ 0<> ^base c!}  ;m
  2351.  
  2352. :m SET:
  2353.     inline{ true ^base c!}  ;m
  2354.  
  2355. :m PRINT:
  2356.     get: self  IF  ." true"  ELSE  ." false"  THEN  ;m
  2357.  
  2358. :m CLASSINIT:    clear: self  ;m
  2359.  
  2360. ;class
  2361.  
  2362.  
  2363. :class    BARRAY  super{ object }  1 indexed
  2364.  
  2365. :m  AT:        \ ( index -- n )
  2366.     inline{ ^elem c@}  ;m
  2367.  
  2368. :m  TO:        \ ( n index -- )
  2369.     inline{ ^elem c!}  ;m
  2370.  
  2371.  
  2372. :m ^ELEM:    \ ( index -- addr )
  2373.     inline{ ^elem}  ;m
  2374.  
  2375. :m FILL:    \ ( value -- )  Fills all elements with value.
  2376.     idxbase  limit 2*  bounds
  2377.     ?DO  dup  i c!  LOOP  drop  ;m
  2378.  
  2379. :m WIDTH:    1  ;m        \ Faster than the default in Object
  2380.  
  2381. :m GETELEM:    \ ( addr -- n )  Fetches one element at addr
  2382.     c@x  ;m
  2383.  
  2384. :m TEST:    at: self  ;m
  2385.  
  2386. ;class
  2387.  
  2388.  
  2389. \ Testing arrays:
  2390.  
  2391. 20 barray bb
  2392.  
  2393. : test4
  2394. ." test4" cr
  2395.     $ 9887 bb 20 + c!
  2396.     12 -> testVal
  2397.     testVal test: bb  $ 87 ?chk
  2398.     120 -> testVal
  2399. \    ." should fail range check and trap - just step past the tw:" cr cr
  2400. \    testval test: bb        \ range check now omitted since Jasik doesn't
  2401.                             \  like it.  Try it after we've loaded our
  2402.                             \  exception handler in zObjInit.
  2403. ;
  2404.  
  2405.  
  2406. \ also we test indexed classes which are subclassed and have
  2407. \  added ivars, to make sure we get the right offset to the
  2408. \  indexed header:
  2409.  
  2410. :class    INDEXED-OBJ  super{ object }
  2411.  
  2412. :m ^ELEM:    ^elem  ;m
  2413.  
  2414. :m LIMIT:    limit  ;m
  2415.  
  2416. :m WIDTH:    idxbase  6 -  w@  ;m
  2417.  
  2418. :m IXADDR:    idxbase  ;m
  2419.  
  2420. :m CLEARX:    \ Erases indexed area.
  2421.     idxbase  limit  width: self  *  erase  ;m
  2422.  
  2423. :m CLASSINIT:    clearX: self  ;m
  2424.  
  2425. ;class
  2426.  
  2427.  
  2428. :class    WARRAY  super{ indexed-obj }  2 indexed
  2429.  
  2430. :m AT:        \ ( index -- n )
  2431.     inline{ ^elem w@x}  ;m
  2432.     
  2433. :m ATT:        ^elem w@x  ;m
  2434.  
  2435. :m TO:        \ ( n index -- )
  2436.     inline{ ^elem w!}  ;m
  2437.  
  2438. ;class
  2439.  
  2440.  
  2441. :class  TRIGTABLE    super{ wArray }
  2442.  
  2443.     3    wArray  AXISVALS
  2444. ;class
  2445.  
  2446. 10 trigtable ttt
  2447. $ 56  ttt $ 26 + w!
  2448.  
  2449. : test5 { \ xx -- }
  2450.     ." test5" cr
  2451.     addr: ttt  -> xx        \ so we can look at it in the debugger
  2452.     3 at: ttt  $ 56 ?chk  ;
  2453.  
  2454.  
  2455. \ Testing object pointers
  2456.  
  2457. var        vv1
  2458.  
  2459. objPtr    ov    class_is var
  2460. objPtr    ov1    class_is var
  2461.  
  2462. objPtr    ob    class_is bool
  2463.  
  2464.  
  2465. : test6
  2466.     ." test6" cr
  2467.     $ 765 put: vv  $ 543 put: vv1
  2468.     vv1 -> ov1  vv -> ov
  2469.     gett: ov1  $ 543  ?chk  get: ov  $ 765 ?chk
  2470.     $ 345 putt: ov  get: ov  $ 345 ?chk  ;
  2471.  
  2472.  
  2473. \ Testing static and public ivars
  2474.  
  2475. :class SIVTEST  super{ var }
  2476. public
  2477. static
  2478. {    var        V1
  2479.     bool    B1
  2480.     byte    B2
  2481. 10    barray    BB
  2482. }
  2483.     bool    BLOC
  2484.     var        VLOC
  2485.     
  2486. :m QQ:    get: v1  get: b1  get: b2 4 at: bb
  2487.         get: vloc  ;m
  2488.  
  2489. :m TEST:
  2490.         66 put: v1  77 put: vloc  ;m
  2491.  
  2492. :m CLASSINIT:
  2493.         32 put: v1  set: b1  33 put: b2  34 4 to: bb
  2494.         set: bloc  34 put: vloc  ;m
  2495. ;class
  2496.  
  2497.  
  2498. sivtest zzz
  2499. sivtest sss
  2500.  
  2501. objPtr myop  class_is sivtest
  2502.  
  2503. : QQQ
  2504. \    classinit: zzz  classinit: sss        \ needed in qpClass, but not here
  2505.     get: ivar> v1 in_class sivtest
  2506.     test: sss
  2507.     get: ivar> b2 in_class sivtest
  2508.     get: ivar> v1 in_class sivtest
  2509.     zzz get: ivar> bloc in class_as> sivtest
  2510.     sss get: ivar> vloc in class_as> sivtest  ;
  2511.  
  2512. : test7
  2513.     ." test7" cr
  2514.     qqq
  2515.     77  ?chk
  2516.     -1    ?chk
  2517.     66    ?chk
  2518.     33    ?chk
  2519.     32  ?chk
  2520. ;
  2521.  
  2522.  
  2523. :class HAHA  super{ object }
  2524.  
  2525.     sivtest    IVsss
  2526.     
  2527. :m QQ:      test: IVsss  get: ivar> vloc IN ivsss  ;m
  2528. ;class
  2529.  
  2530. haha hh
  2531.     
  2532. : test8
  2533.     ." test8" cr
  2534.     classinit: zzz   qq: hh  77 ?chk
  2535.     get: ivar> vloc IN zzz
  2536.     34 ?chk
  2537. ;
  2538.  
  2539.  
  2540. \ Testing late bind to self
  2541.  
  2542. :class VAR+ super{ var }
  2543.  
  2544. :m QQ:    get: [self]        \ should make class general
  2545.         get: [ self ]    \ shouldn't give any error
  2546. ;m
  2547.  
  2548. ;class
  2549.  
  2550. var+ VVV
  2551.  
  2552. \ qq: vvv        \ no need for ?chk since it will give its own error
  2553.  
  2554. : test9
  2555.     ." test9" cr
  2556.     qq: vvv  2drop
  2557. ;
  2558.  
  2559.  
  2560. \ Testing records and unions.  Also, the TEST: method piles up so many
  2561. \  values that this also tests register spilling with a duplicate value!
  2562.  
  2563. :class RECTEST super{ object }
  2564.     var    vv
  2565.     record RR
  2566.     {        var        v1
  2567.             bool    b1
  2568.         3    barray  bbb
  2569.             byte    b3            \ now aligned - unions should normally
  2570.                                 \  start out aligned, but we don't insist
  2571.                                 \  on it
  2572.         union {    byte    b2
  2573.                 var        v2
  2574.                 record {    byte bb1
  2575.                             byte bb2    }
  2576.             }
  2577.             var        v3
  2578.     }
  2579.  
  2580.  
  2581. :m TEST:
  2582.     4 0 to: bbb  5 1 to: bbb  6 2 to: bbb
  2583.     $ 33  put: vv
  2584.     $ 123 put: v1  set: b1
  2585.     $ 124 put: v2  7 put: b3
  2586.     $ 35 put: bb1  $ 36 put: bb2
  2587.     $ 125 put: v3  $ 37 put: b2
  2588.     get: v1  put: b1
  2589.     get: b2  get: v2
  2590.     get: bb1  get: bb2  get: v3
  2591.     addr: rr  36 + @
  2592. ;m
  2593. ;class
  2594.  
  2595. recTest rrr
  2596.  
  2597. : test10
  2598.     ." test10" cr
  2599.     $ 33  addr: vvv !
  2600.     qq: vvv
  2601.     $ 33        ?chk
  2602.     $ 33        ?chk
  2603.     test: rrr
  2604.     $ 125        ?chk
  2605.     $ 125        ?chk
  2606.     $ 36        ?chk
  2607.     $ 37        ?chk
  2608.     $ 37360124    ?chk
  2609.     $ 37        ?chk
  2610.     rrr $ 2C + @  $ 04050607  ?chk
  2611. ;
  2612.  
  2613.  
  2614. \ testing multiple inheritance
  2615.  
  2616. :class INT  super{ object }
  2617.  
  2618.     2    bytes    data
  2619.  
  2620. :m CLEAR:
  2621.     inline{ 0 ^base ! }  ;m
  2622.  
  2623. :m UGET:
  2624.     inline{ ^base w@ }  ;m
  2625.  
  2626. :m GET:
  2627.     inline{ ^base w@x }  ;m
  2628.  
  2629. :m PUT:
  2630.     inline{ obj w! }  ;m
  2631.  
  2632. :m PUTT:    ^base w!  ;m
  2633. :m IPUT:    ^base w!  ;m        \ used in testing mult inheritance
  2634.  
  2635. :m CLASSINIT:  $ 456 put: self  ;m
  2636.  
  2637. ;class
  2638.  
  2639.  
  2640. :class CC  super{ byte int var bool }
  2641.  
  2642. :m TEST:
  2643. iput: self    \ check it compiles
  2644.     uget: self            \ offs should be 0
  2645.     +: self                \ offs should be 4
  2646.     set: self  ;m        \ offs should be E
  2647.  
  2648. :m TEST1:
  2649.     set: self
  2650.     get: super> bool    \ should get -1
  2651.     get: super
  2652. ;m
  2653.     
  2654. :m setValues:
  2655.     9 put: super> byte
  2656.     $ 456  putt: super        \ should go to the int
  2657.     $ 456  put: super> int
  2658.     $ 123  put: super> var
  2659.     set: super
  2660. ;m
  2661.  
  2662. ;class
  2663.  
  2664. cc myCC
  2665.  
  2666. : test11 { \ addr -- }
  2667.     ." test11" cr
  2668.     addr: mycc -> addr
  2669.     setValues: mycc
  2670.     mycc @        $ 09000000    ?chk
  2671.     mycc 4+   @    $ fff40002  ?chk
  2672.     mycc 8 +  @    $ 04560000    ?chk
  2673.     mycc 12 + @ $ ffec0002  ?chk
  2674.     mycc 16 + @    $ 123        ?chk
  2675.     mycc 20 + @ $ ffe40002  ?chk
  2676.     mycc 24 + @ $ ff000000  ?chk
  2677. ;
  2678.  
  2679.  
  2680. :class STRANGE  super{ object }
  2681.     var VV
  2682.     byte BB
  2683. :m GET:  get: vv  get: bb  ;m
  2684. :m PUT:  put: bb  put: vv  ;m
  2685.  
  2686. ;class
  2687.  
  2688.  
  2689. :class    ARRAY  super{ indexed-obj }  4 indexed
  2690.  
  2691. :m AT:        \ ( index -- n )
  2692.     inline{ ^elem @}  ;m
  2693.     
  2694. :m ATT:        ^elem @  ;m
  2695.  
  2696. :m TO:        \ ( n index -- )
  2697.     inline{ ^elem !}  ;m
  2698.  
  2699. :m  +TO:        \ ( n index -- )
  2700.     inline{ ^elem +!}  ;m
  2701.  
  2702. :m -TO:        \ ( n index -- )
  2703.     inline{ ^elem -!}  ;m
  2704.  
  2705. :m FILL:        \ ( value -- )  Fills all elements with value.
  2706.     idxbase  limit 4*  bounds
  2707.     DO  dup  i !  4 +LOOP  drop  ;m
  2708.  
  2709.  
  2710. :m ATEST:
  2711.     1 at: self  ;m
  2712.  
  2713. ;class
  2714.  
  2715.  
  2716. :class MULT    super{ var int array }
  2717.  
  2718. :m MTEST:    $ 456  put: super> int  $ 123  put: super> var
  2719.             uget: super  999 1 to: self  ;m
  2720.             
  2721. :m MAT:        at: self  ;m
  2722.  
  2723. ;class
  2724.  
  2725.  
  2726. objPtr    OO    class_is mult
  2727. objPtr    OOO    class_is int
  2728.  
  2729. :class IVXX    super{ object }
  2730.     10 bytes data2
  2731.     int    i1
  2732.     int    i2
  2733.     130 bytes qqqq        \ Include to check >128 distance
  2734.                         \  index addressing of array qwert
  2735.     9 array qwert
  2736.  
  2737. :m ITEST:
  2738.     $ 8456  dup i1 w!  addr: i2 w!        \ should be equivalent
  2739.     get: i1  uget: i2  66 put: i2
  2740.     99 3 to: qwert  1234 drop  3 at: qwert
  2741.     addr: i2  -> ooo  ;m
  2742.  
  2743. :m GETQWERT:
  2744.     addr: qwert  ;m
  2745. ;class
  2746.  
  2747.  
  2748. int ii
  2749. 3 mult    mm
  2750. ivxx    iv
  2751.  
  2752. : test12
  2753.     ." test12" cr
  2754.     itest: iv
  2755.     $ 63    ?chk
  2756.     $ 8456    ?chk
  2757.     $ ffff8456    ?chk
  2758.     mtest: mm
  2759.     $ 456    ?chk
  2760.     88 iput: mm        \ Note: get: mm will bind to the var, but uget: mm
  2761.                     \ will bind to the int and give 88.
  2762.  
  2763.     get: mm  $ 123    ?chk
  2764.     uget: mm 88        ?chk
  2765. ;
  2766.  
  2767. : test13
  2768. ." test13" cr
  2769.     itest: iv
  2770.     getqwert: iv  3 swap at: **        99    ?chk
  2771.     mtest: mm            $ 456    ?chk
  2772.     1 at: mm            999 ?chk
  2773.     1 mat: mm            999 ?chk
  2774.     1 mm at: mult        999 ?chk
  2775.     1 mm at: []            999 ?chk
  2776.     mm -> oo
  2777.     1 at: oo            999     ?chk
  2778.     1 mat: oo            999     ?chk
  2779.     uget: mm            $ 456    ?chk
  2780.     addr: mm  addr: oo            ?chk  \ Both numbers shd be same
  2781.     uget: ooo            66        ?chk
  2782. ;
  2783.  
  2784.  
  2785. \ testing ivSetup (via deep_classinit: ) - this should put the $123 and
  2786. \  $456 in the var and the int, and store the same offsets in the header
  2787. \  that are already there.
  2788.  
  2789. :class ivsTestClass  super{ var int array }
  2790.     record
  2791.     {    var        v1
  2792.         int        i1
  2793.         byte    b1
  2794.      3     array    a1
  2795.     }
  2796. ;class
  2797.  
  2798. 5 ivsTestClass  ivs1
  2799.  
  2800. : test14 { \ aa -- }
  2801. ." test14" cr
  2802.     deep_classinit: ivs1
  2803.     addr: ivs1 @        $ 123          ?chk
  2804.     addr: ivs1 4 + @    $ FFF4003A    ?chk
  2805.     addr: ivs1 8 + @    $ 04560000    ?chk
  2806.     addr: ivs1 12 + @    $ FFEC0032    ?chk
  2807.     addr: ivs1 16 + @    $ 123        ?chk
  2808.     addr: ivs1 20 + @    $ 04560900    ?chk
  2809.     addr: ivs1 24 + @    $ 0            ?chk    \ array has no name so zero here
  2810.     addr: ivs1 -> aa
  2811.     addr: ivs1 28 + c@    $ 08        ?chk    \ rest of reloc addr can change
  2812.     addr: ivs1 32 + @    $ FFFC000A    ?chk
  2813.     addr: ivs1 36 + @    $ 4            ?chk
  2814.      addr: ivs1 40 + @    $ 2            ?chk
  2815.  ;
  2816.  
  2817.  
  2818. \ Testing temp objects
  2819.  
  2820. :class strxx super{ string }
  2821.  
  2822. :m RELEASE:
  2823.     ." string released" cr  release: super
  2824. ;m
  2825. ;class
  2826.  
  2827. : leaf ;
  2828.  
  2829. : test15 { \ aa bb -- }
  2830. temp
  2831. {    var    v1
  2832.      var    v2
  2833.      strxx s1
  2834. }
  2835.     ." test15" cr
  2836.     ." locreg value:" locreg . cr
  2837.  
  2838.     get: v1  get: v2
  2839.     $ 123    ?chk
  2840.     $ 123    ?chk
  2841.  
  2842. leaf
  2843.     " hello world!" put: s1
  2844.     ." The next line should say hello world!" cr
  2845.     get: s1 type cr
  2846.     ." The next line should say string released" cr
  2847. ;
  2848.  
  2849. :class AAAA super{ object }
  2850.  
  2851. :m CLICK:  { \ part ^ctl action1 action2 x y -- }
  2852.     null
  2853. ;m
  2854.  
  2855. ;class
  2856.  
  2857. aaaa myAAAA
  2858. : test16
  2859. ." test16" cr
  2860.     click: myAAAA   ;
  2861.  
  2862.  
  2863. \ =========== TORTURE runs the test! ============
  2864.  
  2865. : TORTURE
  2866.     ." torture tests start..." cr cr
  2867.     test1 test2 test3 test4 test5
  2868.     test6 test7 test8 test9
  2869.     test10 test11 test12 test13
  2870.     test14  test15  test16
  2871.     cr cr ." torture tests WORKED!!!" cr
  2872. ;
  2873.